阻塞IO下的echo回显实验

我们只关心代码中的业务逻辑和底层阻塞原因

客户端代码

发送数据

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

接受服务端回显的数据

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

服务端代码

采用thread per connection 模型,每个链接分配一个线程来进行数据回显

  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();

发送数据过大时,客户端阻塞的原因分析

C13Yzn.png
在发送数据过大时,客户端会陷入长时间的阻塞状态,发送队列和接受队列的状态如上图,分析代码中的业务逻辑可知,由于客户端在发送完所有数据之后才会接受,在发送的时候将数据放入内核缓冲区,内核缓冲区长度固定,服务端是边读取边发送,所以服务端在向客户端发送回显数据时可能会将发送内核缓冲区填满(此时客户端没有发送完所有元素不会开始读,这样两边都在等待。。。)

解决方式 header + payload 方式进行数据交互

  • 从应用层协议解决这个问题
    每次发送数据之前进行分包,让接收方准备好对应的内存空间后进行接受,具体应用实例

转载于:https://www.cnblogs.com/joeylee97/p/8946767.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值