是";“读取零字节”;从套接字监视POSIX C中TCP/IP断开连接的有效方法?
我目前正在审查一个实现POSIX套接字的C应用程序。此应用程序通过从套接字读取零字节,间歇性地检查与服务器的连接是否有效。然后检查是否设置了errno以确定连接是否正常。这是一个稳健的解决方案吗是";“读取零字节”;从套接字监视POSIX C中TCP/IP断开连接的有效方法?,c,linux,sockets,tcp,posix,C,Linux,Sockets,Tcp,Posix,我目前正在审查一个实现POSIX套接字的C应用程序。此应用程序通过从套接字读取零字节,间歇性地检查与服务器的连接是否有效。然后检查是否设置了errno以确定连接是否正常。这是一个稳健的解决方案吗 uint32_t IsConnected() { char dummy[10]; if(read(global_sockfd, dummy, 0) == -1) { if(errno != EWOULDBLOCK &&
uint32_t IsConnected()
{
char dummy[10];
if(read(global_sockfd, dummy, 0) == -1)
{
if(errno != EWOULDBLOCK && errno != EAGAIN)
return FALSE;
else
return TRUE;
}
else
return TRUE;
}
对。返回值部分对此进行了说明:
这些调用返回接收的字节数,如果
发生错误。发生错误时,errno设置为
指出错误
当流套接字对等方执行有序关闭时
返回值将为0(传统的“文件结束”返回)
不同域(如UNIX和Internet)中的数据报套接字
域)允许零长度数据报。当这样的数据报
接收时,返回值为0
如果请求的字节数不正确,也可能返回值0
从流套接字接收的值为0
TCP套接字是流套接字,因此只要确保recv()
/read()
调用使用大小非零的缓冲区,零返回表示对等方已执行有序关闭
有序关机是两件事之一:关闭套接字或调用它(在这种情况下,使用SHUT_WR或SHUT_RDWR,前者表示它不会发送任何进一步的数据,但能够接收,后者表示它不会发送或接收任何数据)。是。返回值部分对此进行了说明:
这些调用返回接收的字节数,如果
发生错误。发生错误时,errno设置为
指出错误
当流套接字对等方执行有序关闭时
返回值将为0(传统的“文件结束”返回)
不同域(如UNIX和Internet)中的数据报套接字
域)允许零长度数据报。当这样的数据报
接收时,返回值为0
如果请求的字节数不正确,也可能返回值0
从流套接字接收的值为0
TCP套接字是流套接字,因此只要确保recv()
/read()
调用使用大小非零的缓冲区,零返回表示对等方已执行有序关闭
有序关机是两件事之一:关闭套接字或调用它(在这种情况下,使用SHUT_WR或SHUT_RDWR,前者表示它不会发送任何进一步的数据,但能够接收,后者表示它不会发送或接收任何数据)。不,这不是一个健壮的解决方案,原因有二 首先,对于连接的TCP套接字,
read
和recv
将返回零,而不是零−1,在读取所有传入数据且远程对等方已关闭其连接端(使用关闭
或关闭
)之后。您的已连接
在这种情况下将返回TRUE,这是错误的
第二,说(描述的第二段;全部强调我的)
在采取下述任何操作之前,如果nbyte
为零,则read
功能可能会检测并返回下述错误。在没有错误的情况下,或者如果没有执行错误检测,读取功能应返回零,并且没有其他结果
nbyte
是第三个参数,您的IsConnected
提供的参数为零。因此,根据操作系统的不同,IsConnected
可能总是返回TRUE,而不管套接字的状态如何
如果length
参数(相当于read
的nbyte
)为零,则没有说明会发生什么;我认为这可能是一个疏忽,它(以及recvfrom
,recvmsg
,等等)与read
具有相同的特殊行为。因此,将read
更改为recv
本身并不能解决问题。但是,我认为通过将recv
与MSG_PEEK
一起使用,可以实现完全修复:
bool is_connected(int sock)
{
char dummy[1];
ssize_t nread = recv(sock, dummy, sizeof dummy, MSG_PEEK);
if (nread > 0)
return true; // at least one byte of data available
else if (nread == 0)
return false; // EOF
else
return errno == EWOULDBLOCK || errno == EAGAIN;
}
使用MSG_PEEK
可以提供非零长度,因为数据实际上不会被消耗
根据应用程序及其网络协议的细节,您也可以考虑在Socket上。
不,这不是一个健壮的解决方案,原因有两个:
首先,对于连接的TCP套接字,read
和recv
将返回零,而不是零−1,在读取所有传入数据且远程对等方已关闭其连接端(使用关闭
或关闭
)之后。您的已连接
在这种情况下将返回TRUE,这是错误的
第二,说(描述的第二段;全部强调我的)
在采取下述任何操作之前,如果nbyte
为零,则read
功能可能会检测并返回下述错误。在没有错误的情况下,或者如果没有执行错误检测,读取功能应返回零,并且没有其他结果
nbyte
是第三个参数,您的IsConnected
提供的参数为零。因此,根据操作系统的不同,IsConnected
可能总是返回TRUE,而不管套接字的状态如何
如果length
参数(相当于read
的nbyte
)为零,则没有说明会发生什么;我认为这可能是一个疏忽,它(以及recvfrom
,recvmsg
,等等)与read
具有相同的特殊行为。因此,将read
更改为recv
本身并不能解决问题。然而,我认为通过使用recv完全修复是可能的<