Страницы

Опять про QTcpSocket и disconnected

Казалось бы, все понятно и все ситуации разобраны. Ан нет.
Известная история. Как определить, что tcp-соединение разорвано? Ответ - настройки keepalive.

На стороне сокета, читающего данные все работает нормально.
На стороне сокета пишущего данные опять проявился сюрприз.
Если между фактом разрыва и отработкой попыток KeepAlive в сокет не было записано данных, то все отрабатывается штатно. QTcpSocket выбрасывает disconnected.
НО
Если после разрыва в сокет были записаны данные, сигнал о разрыве не выбрасывается. Более того, write фиксирует успех записи данных. bytesToWrite показывает 0, что означает, что данные уже записаны в канал. state сокета показывает QAbstractSocket::ConnectedState.

Не поленился написал тестовый пример для демонстрации описываемого эффекта.
void SocketTransport::onConnected()
{
qDebug()<<"OnConnected";
mSocket.setSocketOption(QAbstractSocket::KeepAliveOption, 1);
int Idle=2;
int Count=3;
int Interval=2;
if(setsockopt(static_cast<int>(mSocket.socketDescriptor()), IPPROTO_TCP, TCP_KEEPIDLE,
&Idle, sizeof(Idle))<0)
qDebug()<<"Error setsockopt IPPROTO_TCP, TCP_KEEPIDLE";
if(setsockopt(static_cast<int>(mSocket.socketDescriptor()),IPPROTO_TCP, TCP_KEEPCNT,
&Count, sizeof(Count))<0)
qDebug()<<"Error setsockopt IPPROTO_TCP, TCP_KEEPCNT";
if(setsockopt(static_cast<int>(mSocket.socketDescriptor()), IPPROTO_TCP, TCP_KEEPINTVL,
&Interval, sizeof(Interval))<0)
qDebug()<<"Error setsockopt IPPROTO_TCP, TCP_KEEPINTVL";
mTimer.start(100);
}


void SocketTransport::writeData()
{
qDebug()<<"BYTES to write"<<mSocket.bytesToWrite()<<mSocket.state();
if(mSocket.state()==QAbstractSocket::UnconnectedState)
{
qDebug()<<"Unconnected state";
QCoreApplication::processEvents();
return;
}
QUuid id=QUuid::createUuid();
QByteArray data=id.toByteArray();
qDebug()<<id<<data.size();
qDebug()<<mSocket.write(data, data.size());
//qDebug()<
//QCoreApplication::processEvents();
}

https://drive.google.com/open?id=0B1NCPMWs3oAFVjk3ZVJSNUZIWTg
Определяем параметры KeepAlive и по таймеру пишем в сокет данные. Выдергиваем кабель и получаем описываемый эффект. (по ссылке архив с полным примером). Все тестировалось в Linux c Qt5.7 и Qt5.8

На всякий случай вчера запостил сообщение в Qt-группу и открыл тикет. Что-то мне подсказывает, что результата не будет. 
Значит придется делать свои heartbeat эхозапросы. Не ждать же пока ситуация разрешится сама.

Если я не прав, очень прошу наставить на путь истинный.

Related Posts Plugin for WordPress, Blogger...