在 C++ 中检查 Socket 是不是已关闭

Posted

技术标签:

【中文标题】在 C++ 中检查 Socket 是不是已关闭【英文标题】:Checking if a Socket has closed in C++在 C++ 中检查 Socket 是否已关闭 【发布时间】:2009-10-19 02:58:09 【问题描述】:

我有一个小型应用程序,它重定向另一个应用程序的标准输出/输入(通常是命令提示符或 Windows 的 bash)。问题是,如果连接被中断,我的进程不知道并且它永远不会因为这条线而关闭:

WaitForSingleObject(childProcess.hThread, INFINITE)

我正在考虑使用这样的循环:

while(true)

     if(ProcessIsDead(childProcess.hThread))
      // close socket and exit
    if(SocketIsDisocnnected(hSocket))
    // close process and exit


我将使用哪些函数来完成此任务?对于 ProcessIsDead,我知道有一个用于获取退出代码的 winapi,但我不知道如何在不调用 recv 的情况下检查套接字是否断开(我不能这样做)

【问题讨论】:

【参考方案1】:

注意:我假设连接的套接字正在通过网络链接进行通信,因为我不确定如果它是本地管道,它将如何断开连接,除非一个进程或另一个进程死亡。

使用socket API中的select()函数查询socket的读取状态。如果以下任何一项为真,select() 将告诉您套接字是“可读的”:

如果已调用listen并且连接处于挂起状态,则accept将成功。 数据可供读取(如果启用了 SO_OOBINLINE,则包括 OOB 数据)。 连接已关闭/重置/终止。

因此,如果 select() 表示套接字是可读的,则调用 recv() 是安全的,如果连接分别被重置或关闭,它将为您提供 WSACONNRESET 或返回 0 字节。 select() 接受一个 'timeout' 参数,如果您想轮询套接字状态,您可以将其设置为适当的时间间隔或零。

关于 select() 函数的信息在http://msdn.microsoft.com/en-us/library/ms740141(VS.85).aspx

【讨论】:

如果数据不总是可用怎么办?如果客户端目前没有执行任何命令,我不希望它断开连接。 如果没有接收到数据,但是连接还在,select() 不会告诉你套接字是可读的。如果套接字不可读,不要调用recv(),一直等到它可读。【参考方案2】:

case-1:如果对端关闭了连接,当你读取 tne 套接字时你会得到 0 个字节(准确地接收到 FIN),是时候关闭套接字了。

case-2:你可以在获得足够的数据包后调用 close() 来关闭套接字。

case-3:如果在读或写套接字时被中断,你会得到EINTR或EAGAIN,然后请重新读/写。

case 1-3 独立于线程,如果有can-read、can-write、error等事件,系统会通知你;所以你有机会处理这些事件。 请尝试不同的 I/O 模型。

【讨论】:

以上是关于在 C++ 中检查 Socket 是不是已关闭的主要内容,如果未能解决你的问题,请参考以下文章

inno setup检查dotnet core是不是已安装[关闭]

检查蜂窝数据是不是已关闭

检查打开的窗口是不是已关闭

如何检查 Windows Universal 10 应用程序是不是已关闭而不是最小化?

在关闭之前检查用户表单是不是已使用 save_click 保存

如何使用 REGEXP_REPLACE 检查字符串中是不是存在值“已关闭”并替换