简体   繁体   English

即使连接不再可用,发送仍然成功?

[英]send succeeds even when the connection is no longer available?

What am I missing? 我想念什么?

I have very simple client and server. 我有非常简单的客户端和服务器。 The server uses recv with timeout (using select ) for 3 seconds. 服务器使用带有超时的recv (使用select )持续3秒钟。 Then it shutdown s and close s the sockets and exits. 然后shutdownclose套接字,然后退出。

The client connects to the server, sleeps 30 seconds and sends very short message. 客户端连接到服务器,睡眠30秒并发送非常短的消息。 The sending is about 27seconds after the server has closed the sockets and exited. 服务器关闭套接字并退出后,发送大约需要27秒。
And send does not fail..? 并且send不会失败..? Why? 为什么? Why it does not return -1 for error? 为什么它不为错误返回-1


Please note: I cut all checks for return codes and removed all logs, to make this as short as I can. 请注意:我削减了所有检查返回码的内容,并删除了所有日志,以使之尽可能短。 Also, I removed all includes, to make this shorter. 另外,我删除了所有包含项,以使其更短。 But it IS a real code. 但这是一个真实的代码。

client code: 客户代码:

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;
}

and server: 和服务器:

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;
}

When I execute it, I see the messages for recv timeout and for successful sent message. 当我执行它时,我看到recv超时和成功发送消息的消息。

Sorry for the long and probably stupid question. 很抱歉这个长期的,可能是愚蠢的问题。

In general you need to read from a socket to get it to notice that the remote end has closed the connection. 通常,您需要读取套接字以获取它,以注意远端已关闭连接。

From the manual page of send (which is just write but with flags): send的手册页中(只是write但带有标志):

No indication of failure to deliver is implicit in a send().  Locally
detected errors are indicated by a return value of -1.

You didnt not close the socket in your client - so this a valid socket. 您没有在客户端中关闭套接字-因此这是有效的套接字。 From send()'s man page 从send()的手册页中

No indication of failure to deliver is implicit in a send().  Locally detected errors are indicated by a return value of -1.

We have this issue with some of our software - if network hardware fails somewhere along the line and it is brought back up again - then either end still thinks the socket is valid - and without keepalives probes - it will stay this way. 我们的某些软件存在此问题-如果网络硬件沿线某处发生故障并再次恢复运行-那么任一端仍然认为套接字有效-并且没有keepalives探针-它将保持这种状态。

ADDING: Have a look at socket options (man setsockopt and man tcp) SO_KEEPALIVE 添加:看一下套接字选项(man setsockopt和man tcp)SO_KEEPALIVE

From TCP man page tcp_keepalive_intvl (integer; default: 75; since Linux 2.4) The number of seconds between TCP keep-alive probes. 从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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 boost asio ssl-连接成功后尝试发送请求 - boost asio ssl - trying to send a request after connection succeeds 用于COM设备的WriteFile()总是成功,即使未连接任何设备,这是否正常? - WriteFile() always succeeds when used for COM device, even if no device is attached, is this normal? 更改系统时区成功一次,然后不再更改 - Changing the system time zone succeeds once and then no longer changes 即使文件描述符不可用,也能有效地监听多个 sockets - Efficiently listening on multiple sockets even when file descriptors are not available 即使CreateWindowEx似乎成功,WinAPI ShowWindow也会失败 - WinAPI ShowWindow fails even though CreateWindowEx seemingly succeeds 当QTest :: qWait(...)成功时,QSignalSpy :: wait(...)失败 - QSignalSpy::wait(…) fails, when QTest::qWait(…) succeeds SFINAE检测:编译失败时替换成功 - SFINAE detection: substitution succeeds when compilation fails 为什么我的 UDP 连接即使没有错误也发送消息? - Why doesn't my UDP connection send messages even though there are no errors? 为什么弱连接时tcp数据发送中断 - Why tcp data send are breaked when weak connection C ++即使有足够的可用内存,程序也会耗尽堆栈内存吗? - C++ Can programs run out of stack memory even when plenty of memory is available?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM