【问题标题】:Testing for a closed socket测试关闭的套接字
【发布时间】:2011-01-27 08:50:41
【问题描述】:

我正在尝试测试已被对等方优雅关闭的已关闭套接字,而不会导致双重发送的延迟命中以引发SIGPIPE

这里的一个假设是,如果套接字关闭,则在它最后一次写入/发送后立即被对等方优雅地关闭。过早关闭等实际错误在代码中的其他位置处理。

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

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

我已经对此进行了测试,它似乎可以工作。但是,我怀疑在我接收数据的最后一位和对等点 FIN 到达之间有一个小窗口,我可以从我的测试 recv 中得到一个误报 EAGAIN

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

【问题讨论】:

  • 另一种方法是 select()(或 poll()),因为它可以同时控制一个 fd 读写,但我不知道它是否真的解决了你关于 FIN 计时的问题。
  • @Giuseppe:不,我认为 select 不会解决时间问题。

标签: c tcp network-programming


【解决方案1】:

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

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

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

可能使这种方法相当可靠的唯一方法,比如接近 99% 是引入与上次读取和尝试的套接字重用之间的连接延迟相关的人为延迟 - 但是,这几乎会破坏性能。

所以,我必须得出结论,虽然这个工具很有用,但也只是勉强有用。

【讨论】:

  • +1 :有趣的测试。人们可以理解为什么在电信领域 90% 的代码是用于管理异常行为 :)
【解决方案2】:

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

【讨论】:

  • 不,我不控制另一端。但是,另一端应该总是发送一条应用程序级别的消息,表明他们正在从他们的一端关闭。只是在现实世界中并不总是会发生这种情况。我可以将其视为常规错误,但我想尝试并在大多数情况下积极捕捉它。
【解决方案3】:

(有点“离题”,抱歉)。也许this discussion 可能对你有帮助。它仍然不能回答您的“FIN”问题,但可以帮助您在程序发送时以更简单的方式对对等方关闭做出反应。

再见

【讨论】:

    猜你喜欢
    • 2010-10-05
    • 2017-03-06
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    相关资源
    最近更新 更多