Izz*_*zzo 1 c sockets linux posix tcp
我目前正在审查一个实现 POSIX 套接字的 C 应用程序。此应用程序通过从套接字读取零字节来间歇性地检查与服务器的连接是否有效。然后检查是否设置了 errno 以确定连接是否正常。这是一个强大的解决方案吗?
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;
}
Run Code Online (Sandbox Code Playgroud)
不,这不是一个强大的解决方案,原因有两个。
首先,对于已连接的 TCP 套接字,在读取所有传入数据并且远程对等方已关闭其连接端(使用或)后read
,recv
将返回零,而不是 ?1 。在这种情况下,您将返回 TRUE,这是错误的。close
shutdown
IsConnected
二、说明的read
说明(说明的第二段;全部强调我的)
在采取下面描述的任何操作之前,如果
nbyte
为零,该read
函数可能会检测并返回如下所述的错误。如果没有错误,或者没有执行错误检测,read
函数将返回零并且没有其他结果。
nbyte
是第三个参数,您IsConnected
将其作为零提供。因此,根据操作系统的不同,无论套接字的状态如何,都IsConnected
可能始终返回 TRUE。
的规范recv
没有说明如果length
参数(相当于nbyte
for read
)为零时会发生什么;我想这可能是一个监督和它(和recvfrom
,recvmsg
等等)是指具有相同的特殊行为read
。因此,更改read
为recv
本身并不能解决问题。但是,我认为使用recv
with可以完全修复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;
}
Run Code Online (Sandbox Code Playgroud)
UsingMSG_PEEK
允许您提供非零长度,因为实际上不会消耗数据。
根据应用程序及其网络协议的详细信息,您可能还需要考虑在套接字上启用 TCP 保持活动数据包。