2016-07-08 25 views
1

我的TCP客户端使用tcp_keepalive_interval = 10s,tcp_keepalive_time = 1stcp_keepalive_probes = 10实现保持活动功能。发送不是感应套接字挂起错误

但是send函数在连接断开超过20秒后没有选择任何错误。理想情况下启用Keepalive后,应将20s(keepalive_interval + keepalive_probes*keepalive_timeE_TIMEDOUT添加到套接字挂起错误。

由于this回答说,

“无论是读取(2)和write(2)第一个尝试甚至以处理任何数据之前获取的 插座任何未决的错误。”

当Keepalive关闭连接时,发送应选择E_TIMEDOUT或任何套接字错误,但不会在下面的代码中发生。

int sockfd = -1; 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { 
     cerr<<"ERROR: Failed to obtain Socket Descriptor!"<<endl; 
     return -1; 
    } 

    //setting keepalive 
    int optval; 
    socklen_t optlen = sizeof(optval); 

    //setting keepalive 
    optval = 1; 
    optlen = sizeof(optval); 
    if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { 
     cerr<<"set keepalive failed"<<endl; 
     return -1; 
    } 
    //setting tcp_keepalive_intvl 
    optval = 10; 
    optlen = sizeof(optval); 
    if(setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { 
     cerr<<"set tcp_keepalive_interval failed"<<endl; 
     return -1; 
    } 
    //setting tcp_keepalive_time 
    optval = 1; 
    optlen = sizeof(optval); 
    if(setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { 
     cerr<<"set tcp_keepalive_time failed"<<endl; 
     return -1; 
    } 
    //setting tcp_keepalive_probes 
    optval = 10; 
    optlen = sizeof(optval); 
    if(setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { 
     cerr<<"set tcp_keepalive_probe failed"<<endl; 
     return -1; 
    } 

    struct sockaddr_in remote_addr; 
    remote_addr.sin_family = AF_INET; 
    remote_addr.sin_port = htons(#port_no); 
    remote_addr.sin_addr.s_addr = inet_addr(#ip_addr); 
    memset(&remote_addr.sin_zero, 0, 8); 
    if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1) { 
     cerr<<"Connect failed with ERRORNO "<<errno<<endl; 
     return -1; 
    } else { 
     cout<<"TcpClient.cpp connected to server"<<endl; 
    } 
    while(1) { 
     char data[20] = "hi hello"; 
     int ret = -1; 
     if((ret = send(sockfd, data, 20, 0)) < 0) { 
      cerr<<"TcpClient.cpp:- failed to send_data, ERROR CODE: "<<errno<<endl; 
      return -1; 
     } else if (ret == 0) { 
      cout<<"send returns 0"<<endl; 
     } else { 
      cout<<"data sent"<<endl; 
     }   
     sleep(1); 
    } 
    getchar(); 
    return 0; 

我使用gcc编译器在linux机器上测试了这段代码。 注:我试了recv相同的代码,它挑剔E_TIMEDOUT错误整齐。

回答

1

你没有等得够久。从http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html

tcp_keepalive_time 

    the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further 

tcp_keepalive_intvl 

    the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime 

tcp_keepalive_probes 

    the number of unacknowledged probes to send before considering the connection dead and notifying the application layer 
与你的(10,10,10)值

因此,保持连接将无法启动,直到最后数据后10秒收到对端。然后,在连接宣告死亡之前,需要10个探测器,每个探测器相隔10秒。

+0

对不起,错误地提到tcp_keepalive_time为10秒而不是1秒。我编辑了这个问题。其实我对Keepalive参数的理解是正确的,但还有一些我错过了。 – Kumar