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

客户端代码

发送数据

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

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



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

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

  • 从应用层协议解决这个问题

    每次发送数据之前进行分包,让接收方准备好对应的内存空间后进行接受,具体应用实例

阻塞IO下的echo回显实验的更多相关文章

  1. Node.js IO处理输入和回显,以及当今web应用程序的发展史

    1.关于Node.js IO处理输入和回显 在Windows终端或者CD中输入   echo  'I must learn about Node.js' 结果将刚刚输入的   echo  'I mus ...

  2. JS 实现下拉框回显

    JS 实现下拉框回显 学习内容: 需求 总结: 学习内容: 需求 用 JS 实现下拉框回显 实现代码 <!DOCTYPE html> <html lang="en" ...

  3. Layui:select下拉框回显

    一..需求场景分析 基于Thymeleaf模板下的layui下选框回显. 二.获得一个Layui标配的下拉框,我们需要在html中填写的内容如下 <div class="layui-f ...

  4. linux c下输入密码不回显

    今天做一个登录程序,需要屏蔽掉密码,于是自己就在网上找资料,找到了一种和linux终端下输入密码方式相同的方法,不显示在终端,具体代码实现如下. #include<stdio.h> #in ...

  5. vue 运用ElementUI,做select下拉框回显

    第一.加载的顺序,应该先加载下拉框要选择的数据,然后在通过编辑查询数据后回显. 第二.要保证select下拉的ID和v-model里边的id保持一致. 第三.elementUI就会自动的将数据回显了. ...

  6. 关于一个socket在阻塞模式下是否还可以使用的实验

    想到一个socket在多线程模式下,是否可以同时使用的问题,比如socket A阻塞在recv,而别的线程用socket A send是否能成功,下面上实验代码 void thread_socket( ...

  7. linux下输入密码不回显

    这几天在做一个登陆的程序,需要将输入的密码屏蔽掉,自己百度,找到了两种方法,先贴下第一种方法, #include<stdio.h> #include<unistd.h> int ...

  8. thymeleaf单选回显,多选回显,选回显,下拉默认选中第一个

    //默认选中第一个<input type ="radio" name="repaymentType" th:each ="repaymentTy ...

  9. SpEL表达式注入漏洞学习和回显poc研究

    目录 前言 环境 基础学习和回显实验 语法基础 回显实验 BufferedReader Scanner SpEL漏洞复现 低版本SpringBoot中IllegalStateException CVE ...

随机推荐

  1. Spring持久化之MyBatis

    MyBatis是一个优秀的轻量级持久化框架,本文主要介绍MyBatis与Spring集成的配置与用法. 1. Spring MyBatis配置 1.1 添加Maven依赖 在pom.xml文件里添加m ...

  2. IP数据包的校验和算法

    1.算法思路: IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下: 在发送数据时,为了计算IP数据包的校验和.应该按如下步骤: (1)把IP数据包的校验和字段置为0: ( ...

  3. iOS开发遇到的坑之一: 开发遇见如下错误:Undefined symbols for architecture arm64

    博客处女作,写得不好望谅解! “for architecture arm64”就是说没有支持arm64,在Build settings里architecture相关的几项需要配置正确 在最近升级coc ...

  4. 使用iptables缓解DDOS及CC攻击

    使用iptables缓解DDOS及CC攻击 LINUX  追马  7个月前 (02-09)  465浏览  0评论 缓解DDOS攻击 防止SYN攻击,轻量级预防 iptables -N syn-flo ...

  5. Python9-列表-day4

    列表list 列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,他是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如: li = [‘a ...

  6. LeetCode(153) Find Minimum in Rotated Sorted Array

    题目 Total Accepted: 65121 Total Submissions: 190974 Difficulty: Medium Suppose a sorted array is rota ...

  7. 关于priority_queue的一些说明

    参考GGBeng 相关定义 优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素.但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大 ...

  8. Spring,Mybatis,Springmvc框架整合项目(第二部分)

    一.创建数据库表 打开Navicat Premium,点击左上角连接,选择mysql   输入你的数据库用户名和密码信息,可以先点击下测试连接,如果显示连接成功,说明能连接到数据库,然后点击确定.如果 ...

  9. PAT Basic 1071

    1071 小赌怡情 常言道“小赌怡情”.这是一个很简单的小游戏:首先由计算机给出第一个整数:然后玩家下注赌第二个整数将会比第一个数大还是小:玩家下注 t 个筹码后,计算机给出第二个数.若玩家猜对了,则 ...

  10. NYOJ 7 街区最短路径问题

    街区最短路径问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 一个街区有很多住户,街区的街道只能为东西.南北两种方向. 住户只可以沿着街道行走. 各个街道之间的间 ...