2016-07-08 27 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