测试关闭的套接字 [英] Testing for a closed socket
问题描述
我正在尝试测试已被对等端正常关闭的已关闭套接字,而不会产生双重发送的延迟命中以引发 SIGPIPE
.
I'm trying to test for a closed socket that has been gracefully closed by the peer without incurring the latency hit of a double send to induce a SIGPIPE
.
这里的一个假设是套接字在最后一次写入/发送后立即被对等方优雅地关闭.像过早关闭这样的实际错误会在代码中的其他地方处理.
One of the assumptions here is that the socket if closed was gracefully closed by the peer immediately after it's last write / send. Actual errors like a premature close are dealt with else where in the code.
如果套接字仍然打开,将会有 0 个或更多字节的数据,我实际上还不想从套接字缓冲区中拉出.
If the socket is still open, there will be 0 or more bytes data which I don't actually want to pull out of the socket buffer yet.
我想我可以调用 int ret = recv(sockfd, buf, 1, MSG_DONTWAIT | MSG_PEEK);
来确定套接字是否仍然连接.如果它已连接但缓冲区中没有数据,我将返回 -1
和 errno == EAGAIN
并返回 sockfd 以供重用.如果它已被对等端正常关闭,我将获得 ret == 0
并打开一个新连接.
I was thinking that I could call int ret = recv(sockfd, buf, 1, MSG_DONTWAIT | MSG_PEEK);
to determine if the socket is still connected. If it's connected but there's no data in the buffer I'll get a return of -1
with errno == EAGAIN
and return the sockfd for reuse. If it's been gracefully closed by the peer I'll get ret == 0
and open a new connection.
我已经对此进行了测试,它似乎有效.但是,我怀疑在我接收数据的最后一位和对等 FIN
到达之间有一个小窗口,我可以从中获得误报 EAGAIN
我的测试 recv
.
I've tested this and it seems to work. However, I suspect there is a small window between when I recv the last bit of my data and when the peer FIN
arrives in which I could get a false-positive EAGAIN
from my test recv
.
这会咬我,还是有更好的方法?
Is this going to bite me, or is there a better way of doing this?
推荐答案
好的,所以我进行了更多测试,这就是我的发现.
OK, so I ran some more tests and this is what I found.
我将我的客户端设置为向服务器发送 HTTP/1.1 Connection: close
消息,导致服务器在最后一次写入数据后调用 close.当我的客户端完成从 GET 事务中读取数据时,它会使用上述方法测试套接字以查看它是否仍处于打开状态,然后尝试发出另一个 GET.
I set my client up to send HTTP/1.1 Connection: close
messages to the server causing the server to call close after it's last write of data. When my client finished reading data from a GET transaction it would test the socket to see if it was still open using the above method and then attempt to issue another GET.
我发现大约 30% 的时间我的测试会在服务器的 FIN
到达之前进行,导致误报和操作失败.
What I found is that approximately 30% of the time my test would occur before the server's FIN
arrived leading to false-positives and failed operations.
可能使这一点相当可靠的唯一方法,比如说接近 99% 是在上次读取和尝试的套接字重用之间引入与连接延迟相关的人为延迟 - 但是,这几乎会降低性能.
Probably the only way to make this reasonably reliable, say close to 99% would be to introduce artificial delays related to the connection latency between the last read and the attempted socket reuse - however, that would pretty much murder performance.
所以,我必须得出结论,虽然这个工具很有用,但也只是勉强有用.
So, I have to conclude that while this tool is useful, it's only marginally so.
这篇关于测试关闭的套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!