Advertisement
Guest User

Untitled

a guest
Jan 18th, 2018
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.85 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. #include <boost/asio.hpp>
  4. #include <glog/logging.h>
  5.  
  6. using namespace std;
  7. using namespace boost::asio;
  8.  
  9. DEFINE_int32(
  10. port, 60000,
  11. "Port number for server / where server is running");
  12. DEFINE_string(
  13. ip_address, "127.0.0.1",
  14. "IP address for server / where server is running");
  15. DEFINE_bool(
  16. server, false,
  17. "Whether to operate in server or client mode (true = server)");
  18. DEFINE_string(
  19. message, "",
  20. "Message for client to send to remote server");
  21.  
  22. // value used as delimiter / for marking the end of a message
  23. const std::string kDelimiter = "#";
  24.  
  25. void runServer();
  26. void runClient();
  27. string readUntilDelimiter(
  28. boost::asio::ip::tcp::socket& socket,
  29. boost::asio::streambuf& readBuffer);
  30. void sendWithDelimiter(
  31. boost::asio::ip::tcp::socket& socket,
  32. const std::string& message);
  33.  
  34. int main(int argc, char *argv[]) {
  35. // setup Google logging and flags
  36. // set logtostderr to true by default, but it can still be overridden by flags
  37. FLAGS_logtostderr = true;
  38. google::InitGoogleLogging(argv[0]);
  39. gflags::ParseCommandLineFlags(&argc, &argv, true);
  40. LOG(INFO) << "Started pa2";
  41.  
  42. // run in server or client mode, depending on the flag
  43. if (FLAGS_server) {
  44. LOG(INFO) << "Running in server mode";
  45. runServer();
  46. } else {
  47. LOG(INFO) << "Running in client mode";
  48. runClient();
  49. }
  50.  
  51. return 0;
  52. }
  53.  
  54. void runServer() {
  55. boost::asio::io_service ioService;
  56. tcp::acceptor acceptor(ioService, tcp::endpoint(tcp::v4(), FLAGS_port));
  57. for (;;) {
  58. // setup a socket and wait on a client connection
  59. tcp::socket socket(ioService);
  60. LOG(INFO) << "Waiting for client to connect";
  61. acceptor.accept(socket);
  62. const auto remoteEndpoint = socket.remote_endpoint();
  63. LOG(INFO)
  64. << "Connected to client ("
  65. << remoteEndpoint.address() << ":" << remoteEndpoint.port() << ")";
  66.  
  67. // wait for a message from our client
  68. LOG(INFO) << "Waiting for message from client";
  69. boost::asio::streambuf readBuffer;
  70. const auto readString = readUntilDelimiter(socket, readBuffer);
  71.  
  72. // reverse the message and send it back
  73. const auto message = string(readString.rbegin(), readString.rend());
  74. sendWithDelimiter(socket, message);
  75. LOG(INFO) << "Sent message \"" << message << "\"";
  76.  
  77. // we're done
  78. LOG(INFO) << "Disconnected client";
  79. }
  80. }
  81.  
  82. void runClient() {
  83. // create local variables for readability
  84. const auto message = FLAGS_message;
  85. const auto remote_ip = FLAGS_ip_address;
  86. const auto remote_port = FLAGS_port;
  87.  
  88. // verify that the message is not empty
  89. if (message.empty()) {
  90. LOG(FATAL) << "Non-empty message must be sent for client";
  91. }
  92.  
  93. // create an ASIO instance and a socket
  94. io_service ioService;
  95. ip::tcp::socket socket(ioService);
  96.  
  97. // connect the socket to the remote system
  98. LOG(INFO) << "Connecting to " << remote_ip << ":" << remote_port;
  99. ip::tcp::endpoint endpoint(
  100. ip::address::from_string(remote_ip), remote_port);
  101. boost::system::error_code error;
  102. socket.connect(endpoint, error);
  103. if (error) {
  104. LOG(FATAL)
  105. << "Connection error: "
  106. << boost::system::system_error(error).what();
  107. }
  108. LOG(INFO) << "Connected to remote endpoint";
  109.  
  110. // send the message
  111. sendWithDelimiter(socket, message);
  112. LOG(INFO) << "Sent message \"" << message << "\"";
  113.  
  114. // wait for a reply
  115. LOG(INFO) << "Waiting for response from server";
  116. boost::asio::streambuf readBuffer;
  117. const auto readString = readUntilDelimiter(socket, readBuffer);
  118. LOG(INFO) << "Received message \"" << readString << "\"";
  119. }
  120.  
  121. void sendWithDelimiter(
  122. boost::asio::ip::tcp::socket& socket,
  123. const std::string& message) {
  124. boost::system::error_code error;
  125. const std::string messageWithDelimiter = message + kDelimiter;
  126. write(socket, buffer(messageWithDelimiter), transfer_all(), error);
  127. if (error) {
  128. LOG(FATAL)
  129. << "Send error: "
  130. << boost::system::system_error(error).what();
  131. }
  132. }
  133.  
  134. string readUntilDelimiter(
  135. boost::asio::ip::tcp::socket& socket,
  136. boost::asio::streambuf& readBuffer) {
  137. // blocking read on the socket until the delimiter
  138. boost::system::error_code error;
  139. const auto bytesTransferred = read_until(
  140. socket, readBuffer, kDelimiter, error);
  141. if (error) {
  142. LOG(FATAL)
  143. << "Read error: "
  144. << boost::system::system_error(error).what();
  145. }
  146.  
  147. // read_until may read more data into the buffer (past our delimiter)
  148. // so we need to extract based on the bytesTransferred value
  149. const string readString(
  150. boost::asio::buffers_begin(readBuffer.data()),
  151. boost::asio::buffers_begin(readBuffer.data()) +
  152. bytesTransferred - kDelimiter.length());
  153. // consume all of the data (including the delimiter) from our read buffer
  154. readBuffer.consume(bytesTransferred);
  155. return readString;
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement