【问题标题】:how to check tcp peer is closed如何检查 tcp peer 是否关闭
【发布时间】:2013-05-16 08:18:19
【问题描述】:

我有一个与远程主机的 TCP 网络连接。(windows 或 linux) 如果远程主机进程终止,recv() 失败 我知道连接已关闭。

但是,有什么方法可以检查远程主机是否 已关闭连接而没有实际接收数据?

关键是,我想定期检查远程主机是否还活着 但我不想提供或接收任何数据。

提前谢谢你

【问题讨论】:

  • 如果您不想提供或接收数据,则无法检查远程主机是否处于活动状态。
  • 我想你想使用 TCP Keep-Alive (Using SO_KEEPALIVE)
  • @Hasturkun 那仍然需要你做一些 I/O,否则你永远都不会发现。
  • @EJP:不完全是。 流中没有其他数据。显然,发送的是零长度数据包。
  • @EJP:哦,等等。我明白你在说什么。他仍然需要在某些时候调用recv()select() 或类似方法来检测连接是否关闭。我仍然认为keepalive在这里是正确的。

标签: linux sockets tcp


【解决方案1】:

需要明确的是,如果连接已正确关闭,recv() 不应失败。它应该返回 EOF(0 字节)。 recv()将失败是连接异常关闭。

要检查连接是否已关闭而实际上没有接收到数据,最好的方法是使用MSG_PEEK 标志调用recvmsg()。只要求一个字节。如果连接已关闭,那么您将收到 EOF(正常关闭)或错误(异常关闭)。如果它还没有关闭,您将获得EAGAIN(假设您将套接字置于非阻塞模式)或一个字节的数据。所以,是的,从技术上讲,你收到了一个字节的数据,但是由于MSG_PEEK 内核没有记录你这样做的事实,所以就好像你没有记录一样。这一切都假设您已经从内核的缓冲区中读取了在预期错误可能发生之前到达的流中的所有数据。

当然rakib 的评论适用:“如果您不想提供或接收数据,则无法检查远程主机是否处于活动状态。”。这意味着这种方法不会检测到远程主机在没有关闭连接的情况下从网络中消失等场景......

【讨论】:

  • 只请求一个字节可能是不够的,因为系统最多可以缓冲 0.5MB,因此只读取 1 个字节看起来就像客户端没有关闭连接。也许偷看 1MB 会发现它。
  • @sheerun 好点。我应该说,一旦您在流缓冲区中赶上到可能发生错误的地步,这将允许您检测到条件。
【解决方案2】:

如果您正在通过 select() 监视套接字的准备读取状态,则 select() 将返回并指示套接字已准备好读取数据。然后,当您尝试 recv() 该数据时,recv() 将失败(如果有错误)或返回 0(如果连接完全关闭,则表示 EOF)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-03
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 2014-04-15
    • 2012-03-08
    • 2010-11-26
    • 1970-01-01
    相关资源
    最近更新 更多