今天在编程的时候遇到了一个小问题,然后做了一点研究,发现了一些以前不知道的东西,也有点惊讶,所以就记录一下。 有些观点可能有错误,欢迎指正。
我们都知道参数有参数。 如果服务器无法及时调用从队列中删除连接,那么UNP告诉我们,服务器的队列满后,服务器将不会响应建立新连接的syn,因此客户端将返回。 但实际上Linux并不是这样的!
设一个程序在8000端口,值为n,不调用; 让客户端程序继续调用。 对客户端的前 n 次调用立即成功返回,这是预期的。 根据 UNP 的说法,所有未来的调用都应该超时并失败,但实际上我看到的是:有些超时失败,有些立即返回成功,有些在明显延迟后返回成功。 使用以下命令观看:
watch " -t -n | grep 8000 | grep -oP '\w+\s*$' | sort | uniq -c"
发现建立的连接数可以无限增加! 再看,发现当客户端发送第一个syn时,服务器会随机选择是否发送syn/ack,这就是tcp握手的第二步。 所以对该行为的解释是:如果这个调用的第一个syn是syn/acked,那么它会立即成功; 如果第一个syn被忽略,而第二个syn由服务器应答,那么它将延迟成功; 如果不幸的是所有三个syn都被服务器忽略,它将返回超时失败。 我花了很长时间,却没有找到任何描述这种行为的文档,如果想确认,只能看源码了。
结论:当tcp队列满时,Linux不会像书上说的那样拒绝连接,而是会随机忽略发起连接的syn。 建立的连接数量可以无限增加,但客户端会随机遇到延迟和超时。
无论是拒绝连接还是随机忽略连接请求都是我们不想看到的,所以作为服务器工程师我们必须要监控这种现象。 我怎样才能在服务器端看到它? 有两种方法,一种是使用:
$ -s | grep
21391 次队列
如果这个数字持续增加,就有麻烦了。
让方法特定于单个方法。 调用、传入并返回一个结构体。 该结构体中的成员是队列的大小,即传入的值; 成员是队列中的连接数。 如果>,那么你应该注意了。 具体调用方法用程序描述:
时间
主机 = ''
端口 = 8000
s = .(., .)
s。 绑定((主机,端口))
s.(88)
#/usr//linux/tcp.h
= .('7B 24I')
而真实:
buf = s.(.,
.,
第1024章)
= .(buf)
, = [11:13]
打印 ':', ,\
':',
时间。 睡觉(1)
可以看到运行开始时的输出是:
: 0 : 88
不断建立与8000端口的连接,然后输出变为:
: 89 : 88
这意味着队列已满。 此时,上面报告的计数也开始不断增加。
----------------------------------------------------------- 稀有点边界-------------------------------------------------- ------------
另外,据我所知,队列满后的行为其实是可以通过的
/proc/sys/net/ipv4/w
改变。 如果它的值设置为1,那么它就会。