我错过了什么?
我有非常简单的客户端和服务器。服务器使用recv
超时(使用select
)3秒。然后是shutdown
s和close
s sockets and exits。
客户端连接到服务器,休眠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
超时和成功发送消息的消息。
抱歉这个漫长且可能很愚蠢的问题。
答案 0 :(得分:3)
通常,您需要从套接字读取以使其注意到远程端已关闭连接。
来自send
的手册页(只有write
但带有标记):
No indication of failure to deliver is implicit in a send(). Locally
detected errors are indicated by a return value of -1.
答案 1 :(得分:1)
您没有关闭客户端中的套接字 - 所以这是一个有效的套接字。来自send()的手册页
No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.
我们的一些软件存在这个问题 - 如果网络硬件在某个地方出现故障而又重新启动 - 那么任何一端仍然认为套接字是有效的 - 并且没有Keepalive探测器 - 它将保持这种状态。
添加: 看一下套接字选项(man setsockopt和man tcp)SO_KEEPALIVE
来自TCP手册页 tcp_keepalive_intvl(整数;默认值:75;自Linux 2.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.