测试封闭的sockets

我正在尝试测试一个被对等端优雅关闭的封闭套接字,而不会产生双重发送的延迟命中以引发SIGPIPE

这里假设的一个假设是,在最后一次写/发送之后,套接字在关闭后会被对等体正常关闭。 像过早关闭这样的实际错误将在代码中的其他地方处理。

如果套接字仍然打开,那么将有0个或更多字节数据,我实际上并不想从套接字缓冲区中取出。

我以为我可以调用int ret = recv(sockfd, buf, 1, MSG_DONTWAIT | MSG_PEEK); 确定套接字是否仍然连接。 如果它已连接但缓冲区中没有数据,我将使用errno == EAGAIN返回-1并返回sockfd以供重用。 如果它已被对等方优雅地关闭,我将获得ret == 0并打开一个新连接。

我已经测试了这个,它似乎工作。 但是,我怀疑在我收集数据的最后一位和同伴FIN到达时之间有一个小窗口,我可以从我的测试recv得到假阳性EAGAIN

这会咬我,还是有更好的方法呢?

好的,所以我再运行了一些测试,这就是我发现的。

我将我的客户端设置为发送HTTP/1.1 Connection: close服务器的消息,导致服务器在上次写入数据后调用close。 当我的客户端从GET事务中读取数据时,它将测试套接字以查看它是否仍然使用上述方法打开,然后尝试发出另一个GET。

我发现大约30%的时间我的测试将在服务器的FIN到达之前发生,导致误报和操作失败。

可能是使这个相当可靠的唯一方法,比如接近99%将引入与最后一次读取和尝试的套接字重用之间的连接延迟相关的人为延迟 – 但是,这几乎会谋杀性能。

因此,我必须得出结论,虽然这个工具很有用,但它只是略有不同。

你控制另一端吗? 执行“干净”关闭套接字的最可靠方法是让另一端发送某种“再见”消息。

(略有“偏离主题”,对不起)。 也许这个讨论对你有帮助。 它仍然没有回答你的“FIN”问题,但可以帮助你在程序发送时以更简单的方式对对等关闭做出反应。

再见