2016-12-20 7 views
0

У меня есть простая программа, так как мой клиент состоит из сокета tcp (QTcpSocket). Коды для моего клиента приведены ниже:QTcpSocket Keep alive option не работает

while (tcpSocket.data()->waitForConnected(maxWaitingTimeToConnect) == false) 
{ 
    tcpSocket.data()->connectToHost(serverIP, serverPort); 
    if (maxRetryNumberToConnect != -1 && retryNumber++ > maxRetryNumberToConnect) 
    { 
     qDebug() << "Socket is disconnected and maximum try for re-connection reached."; 
     return false; 
    } 
    emit sgl_tryToConnect(); 
    // Socket is disconnected and trying to re-connect 
    QThread::msleep(100); 
} 
qDebug() << "Client is connected"; 
qDebug() << tcpSocket.data()->localPort(); 
auto sd = tcpSocket.data()->socketDescriptor(); 
NetworkShared::setSocketOption(&sd); 

который setSocketOption также приводится ниже:

/// Set keepAlive 
int enableKeepAlive = 1; 
/* Set socket FD's option OPTNAME at protocol level LEVEL 
    to *OPTVAL (which is OPTLEN bytes long). 
    Returns 0 on success, -1 for errors. */ 
qDebug() << setsockopt(*socketDescriptor, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive)); 

int maxIdle = 1; /// Seconds 
qDebug() << setsockopt(*socketDescriptor, SOL_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle)); 

int count = 1; /// Send up to 1 keepalive packets out, then disconnect if no response 
qDebug() << setsockopt(*socketDescriptor, SOL_TCP, TCP_KEEPCNT, &count, sizeof(count)); 

int interval = 1; /// Send a keepalive packet out every 1 seconds (after the 1 second idle period) 
qDebug() << setsockopt(*socketDescriptor, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)); 

при запуске программы, все выглядят прекрасно и вариант KeepAlive будет включен для моего гнезда. Но это не работает, когда я отсоединяю кабель на стороне клиента. Я привел свой вывод netstat, ниже которого указывается, что таймер keepalive включен для моего сокета.

tcp  0  0 192.168.2.157:37281  192.168.2.163:4444  ESTABLISHED keepalive (0.16/0/0) 

Я также включил опцию keepalive на стороне сервера точно так же, как на стороне клиента. Теперь у меня есть некоторые вопросы; 1- Когда я должен включить опцию keepalive? После подключения к серверу или перед подключением? 2- Должен ли я написать код для ловли keepalive error в моей программе?

Кстати, моя программа работает в linux mint 17.1, и я также изменил параметры keeplalive в sysctl.conf и proc/sys без vail.

Заранее благодарим за помощь. Реза

+1

Параметр 'netstat' вывод, который вы выложили указывает, что это действительно работает. Неясно, что вы спрашиваете. – EJP

+0

Возможный дубликат [Как обнаружить интернет-разъединение сокетов SSL/TCP, которые были подключены раньше?] (Http://stackoverflow.com/questions/37116838/how-to-detect-internet-disconnection-on-ssl-tcp- sockets-which-connected-bef) – iammilind

+0

Вы ссылались на этот сигнал [QAbstractSocket :: disconnected() не выделяется при отключении коммутатора] (http://www.qtcentre.org/archive/index.php/t- 29469.html). В качестве альтернативы вы также можете использовать различные методы 'waitfor ...()' (т. Е. 'WaitForReadyRead (миллисекунды)'). Тайм-аут может быть установлен на желаемое количество, а затем также проверить, жив ли соединение. Кстати, я новичок в Qt. Вы нашли решение своей проблемы? @EJP, я думаю, что у ОП есть проблема, когда сокет не отключается, даже когда вытаскивается интернет-штепсель (если я правильно понял). – iammilind

ответ

0

Было бы лучше использовать функцию в Qt setSocketOption:

your_socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1); 

перечисление QAbstractSocket :: SocketOption

Данное перечисление представляет опции, которые могут быть установлены на сокете. Если желательны , они могут быть установлены после приема подключенного() сигнала из сокета или после приема нового сокета от QTcpServer.

Примечание: В Windows Runtime QAbstractSocket :: KeepAliveOption должен быть установлен перед подключением сокета.

и для уловом любые ошибки соединения:

connect (your_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), this, &YourClass::onError); 
// ... 

void YourClass::onError(QAbstractSocket::SocketError socketError) 
{ 
    switch(socketError) 
    { 
     case QAbstractSocket::ConnectionRefusedError: 
     // ... 
     // ... 
    } 
} 
+0

Было бы лучше, почему? – EJP

+1

@EJP, потому что у Qt есть свои функции для этого, и странно смешивать Qt и системные функции в этом случае. Также Qt представляет собой кросс-платформенную платформу –

+0

Irrelevant. Если 'setsockopt()' не возвращает -1, он явно работал, так как именно это решит проблему OP? – EJP