windows 在 C++ 中检查 Socket 是否已关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1586773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:18:25  来源:igfitidea点击:

Checking if a Socket has closed in C++

c++windowswinapisocketswinsock

提问by Christopher Tarquini

I have a small application that redirects the stdout/in of an another app (usually command prompt or bash for windows). The problem is that if the connection is interrupted the my process has no idea and it never closes because of this line:

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

WaitForSingleObject(childProcess.hThread, INFINITE)

I was thinking of having a loop with something like this:

我想有一个这样的循环:

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

}

What functions would I use to accomplish this? For ProcessIsDead I know there is a winapi for getting the exit code but I don't know how to check if the socket is disconnected without calling recv (which i cant do)

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

回答by divegeek

Note: I'm assuming the connected socket is communicating over a network link, because I'm not sure how it would become disconnected if it were a local pipe, except by one process or the other dying.

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

Use the select() function in the socket API to query the read status of the socket. select() will tell you the socket is "readable" if any of the following is true:

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

  • If listen has been called and a connection is pending, accept will succeed.
  • Data is available for reading (includes OOB data if SO_OOBINLINE is enabled).
  • Connection has been closed/reset/terminated.
  • 如果已经调用了侦听并且连接处于挂起状态,则接受将成功。
  • 数据可供读取(如果启用 SO_OOBINLINE,则包括 OOB 数据)。
  • 连接已关闭/重置/终止。

So, if select() says that the socket is readable, it is safe to call recv(), which will give you WSACONNRESET or return 0 bytes if the connection was reset or closed respectively. select() takes a 'timeout' parameter, which you can set to an appropriate time interval or zero if you want to poll the socket state.

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

Information on the select() function is at http://msdn.microsoft.com/en-us/library/ms740141(VS.85).aspx

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

回答by Test

case-1: if the peer closed the connection, you'll get 0 bytes when reading tne socket (receive FIN exactly), it's time for you to close the socket.

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

case-2: you could call close() to close the socket after get enough packets.

案例2:您可以在获得足够的数据包后调用 close() 关闭套接字。

case-3: if got interruted when reading or writing the socket, you'll get EINTR or EAGAIN, then please read/write again.

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

cases 1-3 are independently to the thread because if has any events such as can-read, can-write or errors, system will notify you; so you have chances to handle the events. please try different I/O model.

情况1-3与线程无关,因为如果有can-read、can-write或error等事件,系统会通知你;所以你有机会处理这些事件。请尝试不同的 I/O 模型。