测试封闭的插座

Rob*_*nes 10 c network-programming tcp

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

这里假设的一个假设是,在最后一次写入/发送之后,对等体在关闭后立即被对等体优雅地关闭.像过早关闭这样的实际错误将在代码中的其他地方处理.

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

我以为我可以打电话int ret = recv(sockfd, buf, 1, MSG_DONTWAIT | MSG_PEEK);来确定插座是否仍然连接.如果它的连接,但有一个在缓冲区中没有数据,我会得到的回报-1errno == EAGAIN和返回的sockfd重用.如果它被对等方优雅地关闭,我将获得ret == 0并打开一个新连接.

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

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

Rob*_*nes 3

好的,所以我又进行了一些测试,这就是我发现的结果。

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

我发现,大约 30% 的情况下,我的测试会在服务器FIN到达之前进行,从而导致误报和操作失败。

可能要使其相当可靠(比如说接近 99%)的唯一方法是引入与上次读取和尝试套接字重用之间的连接延迟相关的人为延迟 - 然而,这几乎会扼杀性能。

因此,我必须得出结论,虽然这个工具很有用,但作用有限。