• Опять про 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 эхозапросы. Не ждать же пока ситуация разрешится сама.

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

  • Поиск по этому блогу

    Copyright (c) Oleg Shall. Технологии Blogger.