<3>:阻塞IO的试验-echo程序

阻塞意味着会阻塞,而且可能永远阻塞,
看下echo的原型,每个线程一个客户端。
代码位置recipes/tpc/{echo.cc, echo_client.cc}

测试

服务端
[root@bogon bin]# ./echo
客户端
[root@bogon bin]# ./echo_client localhost 1024(1024000,10240000,20488888(20M))

这里写图片描述

可以观察到20MB的时候已经阻塞掉了,why?
观察结果如下:

可以看到服务端的接受队列约有6MB,发送队列大概有4MB,于是有4MB的数据存在发送缓冲区里,接受缓冲区还有6MB的数据等待读取;客户接受缓冲区有900多K的数据,发送缓冲区有4MB的数据。

原因解释:

客户端发(send)完才会读取(receive),
客户端在发的时候,数据先进入内核缓冲区,缓冲区满了后就会阻塞掉;服务端读,并会发送,
客户端发完(send)20MB之前是不会读的(receive),
估算下,如果缓冲区10MB,则发送完10MB,服务端就send,阻塞在send上了,因为它等待client读取,但是client必须send完毕才会读取;所以显示server阻塞在send上,然后它就不会去收(receive)客户端的数据了,它不reveive,则client就阻塞在send上。同时阻塞在send上。

阻塞IO看起来简单,可是一旦阻塞了就没有办法解脱呀,20MB是本机测试的结果,如果用两台机器测试的数据会显著小于此机器(待测试。。。)这个和内核参数有关,主要是TCP的相关设置,如下

[david@localhost ~]$ sysctl -A | grep tcp.*mem
sysctl: permission denied on key 'fs.protected_hardlinks'
sysctl: permission denied on key 'fs.protected_symlinks'
sysctl: permission denied on key 'kernel.cad_pid'
sysctl: permission denied on key 'kernel.usermodehelper.bset'
sysctl: permission denied on key 'kernel.usermodehelper.inheritable'
sysctl: permission denied on key 'net.ipv4.tcp_fastopen_key'
net.ipv4.tcp_mem = 42339    56452   84678
//接受缓冲区,6M多
net.ipv4.tcp_rmem = 4096    87380   6291456
//发送缓冲区,4M多
net.ipv4.tcp_wmem = 4096    16384   4194304

哪里出问题呢?client还是server呢?首先client发送20MB的数据没问题,问题是出在服务端,看待echo服务器每次读4K的数据,读完就发送出去,问题在于没有完整的读取请求。

协议设计:

客户端先发送header,再发送payload。服务器在收到header的时候,先准备一个相应长度的缓冲区,接受到这么多的数据后,开始计算,算出一个响应;拿前面的例子来说,比如说15MB,算完之后将15MB数据发给客户端,这样的话server发的时候也发一个Header,再发送payload。字节流协议需要加上自己的分包措施才行。

这里写图片描述

参考陈硕[网络编程实践]课程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值