微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

QTcpSocket 在工作进程中连续写入避免内存泄漏的最佳实践

如何解决QTcpSocket 在工作进程中连续写入避免内存泄漏的最佳实践

我必须在特定的时间间隔内通过 TCP 套接字向服务器发送单个小数据包。我正在用 Qt 开发。 我的想法是创建继承自 QObject 的类,将 Socket 写入部分放在此类类中的无限循环中,并将其作为单独的线程执行。
它可以工作,但内存泄漏....在这一点上我很迷茫。
这是我到目前为止所做的(某种伪代码......):

Task_SendPacket.h

#ifndef TASK_SENDPACKET_H
#define TASK_SENDPACKET_H

#include <QObject>
#include <QTcpsocket>

class Task_SendPacket : public QObject
{
    Q_OBJECT
public:
    explicit Task_SendPacket(QObject *parent = nullptr);

public slots:
    void startTask();

    void _connected();
    void _readReady();
    void _error(QAbstractSocket::SocketError _Error);

signals:

private:

    QTcpsocket *mpSocket;
    char SomeData[100];
};

#endif // TASK_SENDPACKET_H

Task_SendPacket.cpp

#include "Task_SendPacket.h"

#include <QThread>
#include <QDebug>

Task_SendPacket::Task_SendPacket(QObject *parent)
    : QObject(parent)
{

}

void Task_SendPacket::startTask(){

while(true){

        mpSocket = new QTcpsocket(this);

        connect(mpSocket,&QTcpsocket::disconnected,mpSocket,&QTcpsocket::deleteLater);
        connect(mpSocket,&QTcpsocket::connected,this,&Task_SetSelectedCamera::_connected);
        connect(mpSocket,&QTcpsocket::readyRead,&Task_SetSelectedCamera::_readReady);
        connect(mpSocket,&QTcpsocket::errorOccurred,&Task_SetSelectedCamera::_error);

        mpSocket->connectToHost("192.168.0.1",50100,QTcpsocket::ReadWrite);

        if(!mpSocket->waitForConnected(Protocol::NetworkTimeout_ms)){

            qWarning() << "SS Packet send - Connection timeout";
        }

        if(!mpSocket->waitForBytesWritten(Protocol::NetworkTimeout_ms)){

            qWarning() << "SS Packet send - write timeout";
            mpSocket->disconnectFromHost();
        }

        if(!mpSocket->waitForReadyRead(Protocol::NetworkTimeout_ms)){

            qWarning() << "SS Packet send - read timeout";
            mpSocket->disconnectFromHost();
        }
    
    QThread::msleep(1000);
}

void Task_SetSelectedCamera::_connected(){
    
    if(mpSocket->write(SomeData,100) == -1){
        qWarning() << "Write Header error ";
    };
}

void Task_SetSelectedCamera::_readReady(){

    char DataRead[100] = mpSocket->readAll();

    /* Do stuff with DataRead...*/

    mpSocket->disconnectFromHost();

}

void Task_SetSelectedCamera::_error(QAbstractSocket::SocketError _Error){

    qWarning() << _Error;

}
}

ma​​in.cpp

/* Start Task SetSelectedCamera */
    QThread *ServiceThread1 = new QThread();
    Task_SendPacket *oTaskSendPacket = new Task_SendPacket();
    oTaskSendPacket->movetoThread(ServiceThread1);

    QObject::connect(ServiceThread1,&QThread::finished,oTaskSendPacket,&QObject::deleteLater);
    QObject::connect(ServiceThread1,&QThread::started,&Task_SendPacket::startTask);
    ServiceThread1->start();
    qInfo() << "Task SendPacket started";

如果我让应用程序运行几天,它会增加内存并崩溃。
这是创建新 QTcpsocket、连接它并发送数据的正确方法吗?

谢谢

编辑
我编辑了原始帖子,因为我没有关注正确的点。在我的想法中,新的 QTcpsocket(...) 必须在 while 循环的每次迭代中运行,因为我希望 mpSocket 在每次断开连接时都被标记删除
在第二个实验中(在下面报告),我尝试在 while 循环之前移动套接字部分……但它仍然有效。

mpSocket = new QTcpsocket(this);

connect(mpSocket,&QTcpsocket::deleteLater);
connect(mpSocket,&Task_SetSelectedCamera::_connected);
connect(mpSocket,&Task_SetSelectedCamera::_readReady);
connect(mpSocket,&Task_SetSelectedCamera::_error);

while(true){ 

    mpSocket->connectToHost("192.168.0.1",QTcpsocket::ReadWrite);

    if(!mpSocket->waitForConnected(Protocol::NetworkTimeout_ms)){

        qWarning() << "SS Packet send - Connection timeout";
    }

    if(!mpSocket->waitForBytesWritten(Protocol::NetworkTimeout_ms)){

        qWarning() << "SS Packet send - write timeout";
        mpSocket->disconnectFromHost();
    }

    if(!mpSocket->waitForReadyRead(Protocol::NetworkTimeout_ms)){

        qWarning() << "SS Packet send - read timeout";
        mpSocket->disconnectFromHost();
    }

    QThread::msleep(1000);
}

那么现在的问题是:

  1. 在每次迭代时创建一个新的 QTcpsocket 是否正确?
  2. 为什么断开连接后套接字仍然工作(因为我做 收到断开连接......我跟踪了)

解决方法

我的耻辱!
很多地方我都错了,但请原谅我,我还年轻,花哨。

我想在这里发布我犯过的错误,希望它可以帮助其他人,因为我认为我已经得到了这个错误的解决方案,因为我之前在 RTOS 编程方面的性经验影响了我。

>

首先
永远不要将无限 while 循环放入 QThread 或 moveToThread(...) 到 QThread 的 QObject 中。这是因为 while 循环会阻止 QEventLoop 运行。一切都会被困在里面

while(true){

...

}

应用程序的任何生命周期(包括信号和槽)都不会继续!

然后 - 信号/插槽卡住
我本应该怀疑一些事情,因为没有

...
if(!mpSocket->waitForBytesWritten(Protocol::NetworkTimeout_ms)){

    qWarning() << "SS Packet send - write timeout";
    mpSocket->disconnectFromHost();
}

if(!mpSocket->waitForReadyRead(Protocol::NetworkTimeout_ms)){

    qWarning() << "SS Packet send - read timeout";
    mpSocket->disconnectFromHost();
}
...

没有ReadyRead 信号,没有BytesWritten 信号等等。这是(显然……现在)因为这些函数正在阻塞,并且由于我的无限循环阻塞了信号/插槽逻辑,因此没有其他方法可以让我的 QTcpSocket 工作。如果应用程序生命周期正常,信号和槽就可以正常工作,否则......它们不会。

最后 - deleteAater() 不起作用
我不明白的最后一件事是为什么,把我的

mpSocket = new QTcpSocket(this);

在while循环之前(应该在每次迭代时删除套接字,套接字仍然可以工作。
这也是因为如果 QEventLoop 不工作,套接字的 deleteLater() 将不起作用......顺便说一下,这也是(我认为)我的应用程序泄漏内存的原因!

现在我已经重新实现了 QTimer 逻辑并且它工作正常。


我认为,我被欺骗的原因是来自实时操作系统的基本思想是在每个线程中都有一个 init 部分和一个循环部分。这就是我寻找无限循环的原因...

我仍然怀疑如何在没有以下情况下在 QThread 中进行无限循环:

  1. 搞乱应用逻辑
  2. 使用 QTimer

谢谢

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。