Echo echo experiment under blocking IO

We only care about the business logic in the code and the underlying blocking reasons

client code

send data

  std::string message(len, 'S');
  int nw = stream->sendAll(message.c_str(), message.size());
  printf("sent %d bytes\n", nw);

Receive the data echoed by the server

  std::vector<char> receive(len);
  int nr = stream->receiveAll(receive.data(), receive.size());
  printf("received %d bytes\n", nr);

server code

Using the thread per connection model, each link allocates a thread for data echo

  InetAddress listenAddr(3007);
  Acceptor acceptor(listenAddr);
  printf("Accepting... Ctrl-C to exit\n");
  int count = 0;
  bool nodelay = argc > 1 && strcmp(argv[1], "-D") == 0;
  while (true)
  {
    TcpStreamPtr tcpStream = acceptor.accept();
    printf("accepted no. %d client\n", ++count);
    if (nodelay)
      tcpStream->setTcpNoDelay(true);
    // C++11 doesn't allow capturing unique_ptr in lambda, C++14 allows.
    std::thread thr([count] (TcpStreamPtr stream) {
      printf("thread for no. %d client started.\n", count);
      char buf[4096];
      int nr = 0;
      while ( (nr = stream->receiveSome(buf, sizeof(buf))) > 0)
      {
        int nw = stream->sendAll(buf, nr);
        if (nw < nr)
        {
          break;
        }
      }
      printf("thread for no. %d client ended.\n", count);
    }, std::move(tcpStream));
    thr.detach();

Analysis of the cause of client blocking when sending data is too large


When the sending data is too large, the client will be stuck in a blocking state for a long time. The status of the sending queue and the receiving queue is as shown in the figure above. After analyzing the business logic in the code, we can see that since the client will accept all the data after sending it When the data is put into the kernel buffer, the length of the kernel buffer is fixed, and the server sends while reading, so the server may fill up the sending kernel buffer when sending echo data to the client (at this time the client The end will not start reading until all elements have been sent, so both sides are waiting...)

Solution header + payload method for data interaction

  • Solve this problem from the application layer protocol
    . Packetize before sending data each time, let the receiver prepare the corresponding memory space and accept it. Specific application examples

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324887096&siteId=291194637