QTcpSocket状态总是连接,甚至拔出以太网线 [英] QTcpSocket state always connected, even unplugging ethernet wire

查看:8119
本文介绍了QTcpSocket状态总是连接,甚至拔出以太网线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个QTcpSocket和我读入一个循环。每次一个完整的数据包被读取,或有一个错误,我手动检查套接字在循环内的状态,与:

I have a QTcpSocket and I am reading into a loop. Each time a full packet has been read, or there has been an error, I manually check the status of the socket inside the loop, with:

    while(true){
    if(socket->state()==QAbstractSocket::ConnectedState){
        qDebug()<<"Socket status: connected. Looking for packets...";
        if(socket->waitForReadyRead(2000)){
        //...
    }

当我执行de程序时,一旦连接并且循环开始,它总是打印 qDebug()<<Socket status:connected。 ;然后停留在 waitForReadyRead ,直到一些数据准备好被读取。

When I execute de program, once connected and the loop starts, it always prints qDebug()<<"Socket status: connected. Looking for packets..."; and then stucks at waitForReadyRead until some data is ready to be read.

问题是没有检测到断开连接。如果我从网络断开与操作系统选项,或者即使我拔下以太网线,它的行为相同:套接字状态等于 QAbstractSocket :: ConnectedStat e,因此它继续

The problem is that disconnections are not detected. If I disconnect from network from the OS options, or even if I unplug the ethernet wire, it behaves the same: Socket state equals QAbstractSocket::ConnectedState, so it goes on, but without receiving anything of course.

我也尝试检测断开连接 disconnected()连接)到重新连接功能:

I also tried to detect disconnections connecting disconnected() signal (after fist connection) to a reconnect function:

// Detect disconnection in order to reconnect
    connect(socket, SIGNAL(disconnected()), this, SLOT(reconnect()));

void MyClass::reconnect(){
    qDebug()<<"Signal DISCONNECTED emitted. Now trying to reconnect";
    panelGUI->mostrarValueOffline();
    socket->close();
    prepareSocket((Global::directionIPSerialServer).toLocal8Bit().data(), 8008, socket);
    qDebug()<<"Reconnected? Status: "<<socket->state();
}

但是信号永远不会发生,因为这个代码从不执行。这是逻辑的,因为它看起来套接字状态总是 ConnectedState

But signal is never emited, because this code is never executed. Which is logical, since it looks like socket state is always ConnectedState.

如果我再次插入,并再次开始接收数据,但我确实想检测断开连接,在GUI显示断开连接。

If I plug again, connection is restored and starts to receive data again, but I do want to detect disconnections to show "Disconnected" at the GUI.

为什么QTcpSocket行为这样,我如何解决这个问题?

Why is QTcpSocket behaving this way, and how can I solve this problem?

编辑:我在类构造函数中创建套接字,然后初始化调用prepareSocket函数:

I'm creating socket at the class constructor, and then initialising calling prepareSocket function:

socket = new QTcpSocket();
socket->moveToThread(this);

bool prepareSocket(QString address, int port, QTcpSocket *socket) {
    socket->connectToHost(address, port);
    if(!socket->waitForConnected(2000)){
        qDebug()<<"Error creating socket: "<<socket->errorString();
        sleep(1);
        return false;
    }
    return true;
}


推荐答案

Qt论坛


如果在一段时间内没有交换数据,TCP将开始发送
保持活动段(基本上,确认的
号的ACK段设置为当前序列号减去1)。另一个对等体
然后回复另一个确认。如果在一定数量的探测段中未收到该确认,则
将自动丢弃。小问题是内核启动
发送保持活动段在2小时后,因为连接
变得空闲!因此,你需要改变这个值(如果你的操作系统
允许)或者在你的
协议(像许多协议,例如SSH)中实现自己的保持活动机制。 Linux允许您使用setsockopt更改

If no data is exchanged for a certain while, TCP will start sending keep-alive segments (basically, ACK segments with the acknowledgement number set to the current sequence number less one). The other peer then replies with another acknowledgement. If this acknowledgment is not received within a certain number of probe segments, the connection is automatically dropped. The little problem is that the kernel starts sending keep-alive segments after 2 hours since when the connection becomes idle! Therefore, you need to change this value (if your OS allows that) or implement your own keep-alive mechanism in your protocol (like many protocols do, e.g. SSH). Linux allows you to change it using setsockopt:



int enableKeepAlive = 1;
int fd = socket->socketDescriptor();
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));

int maxIdle = 10; /* seconds */
setsockopt(fd, IPPROTO_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));

这篇关于QTcpSocket状态总是连接,甚至拔出以太网线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆