2016-07-08 1 views
1

내 TCP 클라이언트가 tcp_keepalive_interval = 10s, tcp_keepalive_time = 1stcp_keepalive_probes = 10의 연결 유지 기능을 구현합니다.보내기가 소켓 보류 중 오류를 감지하지 않습니다.

그러나 연결이 20 초 이상 깨진 후에 send 함수는 오류를 선택하지 않습니다. 이상적으로 keepalive가 활성화 된 상태에서 소켓 보류 오류에 20 초 (keepalive_interval + keepalive_probes*keepalive_time) E_TIMEDOUT을 추가해야합니다.

"모두 읽기 (2) 및 (2) 첫째도 데이터를 처리하기 전에 소켓에 대기중인 오류를 검색 할 수 있습니다. 쓰기", this 대답은 말한다으로

연결은 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에서 : 마지막 데이터 후 10 초 피어에서 수신 될 때까지 (10, 10, 10)의 가치관에 따라서

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 개의 프로브는 연결이 해제되기 전에 승인되지 않아야합니다.

+0

죄송합니다. 1 초 대신 tcp_keepalive_time을 10 초로 잘못 언급했습니다. 나는 그 질문을 편집했다. 실제로 keepalive 매개 변수에 대한 나의 이해는 정확하지만 내가 누락 된 다른 것이 있습니다. – Kumar

관련 문제