Python Socket 编程:服务器端重置客户端连接解决之道

本系列将会关注在一个 FPGA 网络加速器项目测试中遇到的网络问题与解决之道,Python socket 测试脚本编程等问题

实验室在 FPGA 上实现了一个协议栈,前期的工作已经进行很多了,笔者现在主要负责测试协议栈的性能和查找 BUG。

测试的方法很多,实验室也有专业的网络分析仪,但综合各方面考虑下来,还是先通过自己写 Python 脚本对一些基础功能进行测试,之后视情况再考虑要不要使用网络分析仪。(最主要的是现在还用不来),通过 Python 脚本编程能够在熟悉网络和 Python 编程的同时,完成测试的任务,这样也是极好的。

在这个过程中遇到一些问题,希望能够记录下来,给有同样问题的朋友以帮助。

脚本功能

为了测试协议栈的建断链能力, 笔者写了一个脚本,依次建立 500 个连接后,发送客户端向服务器发送自己连接的源端口号,依次关闭所有连接。先在两台电脑间测试。

问题现象

当时问题的表面现象是建立连接的速度很慢,通过 wireshark 抓包发现:

服务器一直重置客户端发来的 SYN 包,导致客户端 SYN 数据包退后半秒重传,直接导致了连接建立速度缓慢。

那么问题就转化为为什么服务器会重置客户端的 SYN 包,带着这个问题,我问了下 Bing。服务器 RST 客户端一般是因为服务器自身的问题:

1.服务器上该连接的进程已经被释放,可能是客户端之前终止了连接,发出了 FIN 包,并且被服务器接收,但某个数据包迟到了,服务器在接收了数据包后,会向客户端发出 RST 包。

2.服务器本身奔溃或者刚从奔溃中恢复,丢失了全部的连接信息,好似遇到了车祸失忆。此时再有之前的连接的数据包到达,服务器只能说:“我不认识你了,但我能重新认识你一次么?”,发出 RST 重置包。

我们的问题显然不属于上面两种基本的情况,但总体上 RST 信号说明服务器无法接收连接。

问题解决

之后的检索指向了 socket.listen( ) 的参数,让我恍然大悟了,我之前的参数设置的都是 1,将参数改大,比如改为 20 后,发送连接建立的速度就大大提升了。

思考

自然而然,我们会觉得 listen 函数的参数代表的是服务器所能接收的最大连接数,但其实并不正确。API 手册上这么解释这个参数:

number of unaccepted connections that the system will allow before refusing new connections

我感觉参数可以理解为等待连接(v)的连接(n)的缓冲区大小,参数本身和服务器所能提供的最大连接数没有直接关系,只和建立连接的速度有关。当连接的建立速度过快,等待连接的连接超出缓冲区的大小,服务器就只能直接重置这些 SYN 连接,使它们退后半秒重发。

结语

本文讨论了服务器重置客户端 SYN 连接建立请求的一种情况,以及相对应的 Python Socket 编程函数参数的含义。通过网络检索以及 API 手册解决了相应的问题。