即使连接不再可用,发送也会成功
send succeeds even when the connection is no longer available?
我错过了什么?
我有非常简单的客户端和服务器。服务器超时使用recv
(使用select
) 3秒。然后shutdown
s和close
s作为插座和出口。
客户端连接到服务器,休眠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
超时和成功发送消息的消息。
很抱歉,这个问题很长,而且可能很愚蠢。
一般情况下,您需要从套接字读取以使其注意到远程端已关闭连接。
从send
的手册页(这只是write
,但有标志):
No indication of failure to deliver is implicit in a send(). Locally
detected errors are indicated by a return value of -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探测——它会保持这种状态。
添加:查看socket选项(man setsockopt和man tcp) SO_KEEPALIVE
来自TCP手册页tcp_keepalive_intvl(整数;默认值:75;自Linux 2.4起)TCP keepalive探测之间的秒数。
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.
相关文章:
- cmake在我的项目中所需的所有静态库都不成功
- 尽管测试成功,CppUnit测试核心仍被丢弃.为什么
- 当套接字连接断开时检测C/C++Unix
- 如何让LLDB在成功时退出,在失败时等待
- 有没有办法知道Tracer是否成功地完全连接到了jaegerclientcpp中的jaeger后端服务器
- 无法在windows上使用mingw将sqlite3与c连接
- 为什么 WinInet 在通过 FQDN 连接时无法通过协商自动进行身份验证,但如果通过 IP 连接则成功?
- 连接四个成功的组合检查适用于大多数情况,但不适用于某些情况
- UDP 连接始终成功
- QTcpSocket 在几次连接成功后发出"Connection Refused Error"?
- 试图通过C ++中的套接字进行连接,但没有成功
- C++ODBC检查连接是否成功
- 尽管连接成功,但未调用插槽
- 客户端套接字连接() 在服务器 accept() 超时后成功
- 即使连接不再可用,发送也会成功
- 在多次成功连接之后,c++停止连接到DB
- 如何确保在关闭连接之前成功发布最后一条AMQP消息
- 客户端连接()失败,服务器端接受()成功.为什么
- QTcpClient成功连接,但未连接到我的服务器.它在哪里连接
- Boost asio SSL -连接成功后尝试发送请求