我遗漏了什么?
我有非常简单的客户端和服务器。服务器使用带有超时的recv (使用select) 3秒。然后它的shutdowns和close的套接字和出口。
客户端连接到服务器,睡上30秒并发送非常短的消息。发送大约是在服务器关闭套接字并退出之后的27秒。
send不会失败..?为什么?为什么它不返回-1错误?
请注意:我切断了所有的检查返回代码和删除所有的日志,以使这个尽可能短。另外,我删除了所有的包含,以使这个更短。但这是一个真正的密码。
客户代码:
int main( int argc, char* argv[] )
{
addrinfo hints;
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
addrinfo *res;
getaddrinfo( "127.0.0.1", "1313", &hints, &res );
int nSocketFD = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
assert( -1 != connect( nSocketFD, res->ai_addr, res->ai_addrlen) );
freeaddrinfo( res ); // free the linked-list, we don't need it anymore
sleep( 30 );
if( send( nSocketFD, "bla", 4, 0 ) > 0 )
{
printf( "Message successfully sent!\n" );
}
close( nSocketFD );
return 0;
}和服务器:
int main()
{
addrinfo hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
addrinfo *res; // will point to the results
getaddrinfo( NULL, "1313", &hints, &res );
int nSocketFD = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
bind( nSocketFD, res->ai_addr, res->ai_addrlen );
freeaddrinfo( res ); // free the linked-list
listen( nSocketFD, 1 );
sockaddr_storage their_addr;
socklen_t addr_size = sizeof( sockaddr_storage );
int nAcceptedSocket = accept( nSocketFD, (sockaddr*)&their_addr, &addr_size );
assert( -1 != nAcceptedSocket );
fd_set fds;
FD_ZERO( &fds );
FD_SET( nAcceptedSocket, &fds );
timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;
if( 0 == select( nAcceptedSocket + 1, &fds, NULL, NULL, &tv) )
{
printf( "recv timeout! Exiting..\n" );
shutdown( nSocketFD, SHUT_RDWR );
close( nSocketFD );
shutdown( nAcceptedSocket, SHUT_RDWR );
close( nAcceptedSocket );
return 1;
}
assert( false );
return 0;
}当我执行它时,我会看到recv超时和成功发送消息的消息。
很抱歉提出这个很长很可能很愚蠢的问题。
发布于 2011-11-16 17:05:25
通常,您需要从套接字中读取以使它注意到远程端已经关闭了连接。
从send的手册页面(它只是write,但带有标志):
No indication of failure to deliver is implicit in a send(). Locally
detected errors are indicated by a return value of -1.发布于 2011-11-16 17:11:14
您没有关闭客户端的套接字,因此这是一个有效的套接字。从send()的手册页
No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.我们的一些软件存在这个问题--如果网络硬件在这条线上的某个地方出现故障,并再次恢复--那么任何一端都仍然认为套接字是有效的--如果没有保持生命的探测--它将保持这种状态。
添加:查看套接字选项(man和man ) SO_KEEPALIVE
在TCP手册页tcp_keepalive_intvl (整数;默认值: 75;自Linux2.4)中,TCP保持活动探测之间的秒数。
tcp_keepalive_probes (integer; default: 9; since Linux 2.2)
The maximum number of TCP keep-alive probes to send before giving up and killing the connection if no response is obtained from the other end.
tcp_keepalive_time (integer; default: 7200; since Linux 2.2)
The number of seconds a connection needs to be idle before TCP begins sending out keep-alive probes. Keep-alives are only sent when the SO_KEEPALIVE socket option is enabled. The default value is 7200 seconds (2 hours). An idle connection is terminated after approximately an additional 11 minutes (9 probes an interval of 75 seconds apart) when keep-alive is enabled.
Note that underlying connection tracking mechanisms and application timeouts may be much shorter.https://stackoverflow.com/questions/8155607
复制相似问题