首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >发送成功,即使当连接不再可用?

发送成功,即使当连接不再可用?
EN

Stack Overflow用户
提问于 2011-11-16 17:01:50
回答 2查看 778关注 0票数 2

我遗漏了什么?

我有非常简单的客户端和服务器。服务器使用带有超时的recv (使用select) 3秒。然后它的shutdowns和close的套接字和出口。

客户端连接到服务器,睡上30秒并发送非常短的消息。发送大约是在服务器关闭套接字并退出之后的27秒。

send不会失败..?为什么?为什么它不返回-1错误?

请注意:我切断了所有的检查返回代码和删除所有的日志,以使这个尽可能短。另外,我删除了所有的包含,以使这个更短。但这是一个真正的密码。

客户代码:

代码语言:javascript
复制
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;
}

和服务器:

代码语言:javascript
复制
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超时和成功发送消息的消息。

很抱歉提出这个很长很可能很愚蠢的问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-16 17:05:25

通常,您需要从套接字中读取以使它注意到远程端已经关闭了连接。

send的手册页面(它只是write,但带有标志):

代码语言:javascript
复制
No indication of failure to deliver is implicit in a send().  Locally
detected errors are indicated by a return value of -1.
票数 3
EN

Stack Overflow用户

发布于 2011-11-16 17:11:14

您没有关闭客户端的套接字,因此这是一个有效的套接字。从send()的手册页

代码语言:javascript
复制
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保持活动探测之间的秒数。

代码语言:javascript
复制
   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.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8155607

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档