2017年8月23日 星期三

[QT] 使用QT設定 TCP/IP KeepAlive

在TCP/IP的機制下所建立的連線,如果Server/Client雙方都沒有要求執行結束的 Four-way handshake,則在TCP/IP機制下,雙方會認為對方一直連線中,直到Timeout结束後才會斷線。通常Timeout時間依據不同的作業系統而有些差異,但時間單位都是小時等級的,故就會發生如對方機器電源已斷電,但程式還是一直保持在E「STABLISHED」的狀態。


如果要解決這個問題,就可以使用TCP/IP 的KeepAlive機制,顧名思義,就是雙方定時回報還活著。範例如下,
QTcpSocket *_socket = new QTcpSocket(this);
if ( _socket != NULL ) {
    _socket->connectToHost(_address, _port);
    if ( _socket->waitForConnected(1000)) {
        int fd = _socket->socketDescriptor(); //一定要連線成功才可取得 descriptor
        int enableKeepAlive = 1;
        setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
        int maxIdle = 10;/* seconds */
        setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
        int count = 3;//send up to 3 keepalive packets out, then disconnect if no response
        setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &count, sizeof(count));
        int interval = 2;//send a keepalive packet out every 2 seconds (after the 5 second idle period)
        setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
    }
}

而Linux的系统預設值如下,(注意:修改該參數則會影響到所以的Socket設定)
#cat /proc/sys/net/ipv4/tcp_keepalive_time 7200
#cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75
#cat /proc/sys/net/ipv4/tcp_keepalive_probes 9

Reference : 
[1] QTcpSocket狀態總是連接,甚至連接到乙太網

沒有留言:

張貼留言