networkprogramming
networkprogramming copied to clipboard
有关tcp_max_syn_backlog不对SYN_RECV队列限制的讨论
看了你的笔记,我运行了你的代码,我这边不断启动client连接server,SYN_RECV状态的连接数是不断上升的。
uname -a Linux centos-linux.shared 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
运行过程
- python server.py
- watch -n 1 "sudo netstat -natp | grep 7777" // 使用watch命令监控状态
- python client.py & // 不断执行多次

所以我觉得你一定是实验中什么环节错误了,tcp_max_syn_backlog参数即使内核版本不同,也不会随便改含义的,再确定下你的实验步骤。
我这边又测了一下, 结果还是和原先一样, 这次我分别在两台机器上测的...
下面这张是listen(2)的截图, 在全连接队列已满的情况下, 又同时启动了4个client.py, 只能出现2个SYN_RECV连接.

然后下面这张是listen(5)的, 这次启动了6个, 最多出现5个SYN_RECV(只不过很快就变成了4个).

这次我没有限制tcp_max_syn_backlog的值, 默认为128.
好吧,我明确下场景。
下面这张是listen(2)的截图, 在全连接队列已满的情况下, 又同时启动了4个client.py, 只能出现2个SYN_RECV连接.
如果listen(2)的话,按照你的server.py程序,服务端会accpet一次(代码第9行)
正常情况下会出现4条ESTABLISHED状态连接,分别是:
- 已经完成连接的
ESTABLISHED:1条 - 处于
ESTABLISHED队列 :3条(backlog+1)
目前这一步是正确的哈?
然后你又启动了4个client再去连,只会出现2个SYN_RECV?
是的, 多余的2个连接压根就没出现(在这4个客户端那边查看时, 连接状态都是ESTABLISHED, 不过connect函数一直没能返回).
connect返回了,只是在read()函数那里读数据,因为没有数据阻塞了,你在connect()之后加输出就可以看到了。
conn_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn_fd.connect(('127.0.0.1', 7777))
print("connect returned")
原因见这里:https://blog.csdn.net/yangbodong22011/article/details/69802544
OK, 纠正一下, 之前的两次测试分别在Fedora 24和Ubuntu 16.04下进行, 都是桌面版.
刚才又尝试在CentOS7下做了一遍(也是桌面版)...这次listen(2)没有限制住, 多次执行client.py产生了多个SYN_RECV的连接. 这也推翻了我之前backlog参数影响两个队列长度的结论. 尴尬.
不过tcp_max_syn_backlog内核参数也没能限制住SYN_RECV的长度, 等我明天再试试.
不过tcp_max_syn_backlog内核参数也没能限制住SYN_RECV的长度, 等我明天再试试.
没能限制住?这个是指你启动超过了128个client,同时SYN_RECV队列长度超过了128?
我觉得版本应该不影响的,即使不同内核版本策略有更新,但是SYN_RECV队列总是要的,而且长度总是需要控制的,用uname -a贴下你不同发行版上Linux内核版本。
$ uname -a
内核版本
CentOS7:
Ubuntu16.04:
Fedora24:

之所以说没能限制住(CentOS 7下), 是因为我手动将tcp_max_syn_backlog修改成了5(listen(2)), 然后在全连接队列已满的情况下, 又同时启动了15个客户端, 然后最多出现了9个SYN_RECV的连接.

