使用Qtcpsocket中的flush()方法后导致release版本运行不稳定问题

YouNeverCanTell 2015-02-04 02:32:06
如题,使用Qt做的客户端启动后有两个线程,一个是主线程,一个是发送心跳线程,两线程使用同一个全局的Socket;
Socket每次write()后使用flush()清空缓存使消息马上发送到服务端,否则debug版本会出现心跳不及时发送现象;
除此之外debug版本比较稳定。现在测试release版本时,发现客户端运行一段时间后(半个小时左右,不做任何操作,程序内部会每隔4秒向服务端发送一次心跳)就会出现runtime error,试过很多方法都没有效果,但是发现把每次write()完的flush()操作注释掉以后就比较稳定。请问flush()是否会导致程序不稳定?
...全文
2956 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
YouNeverCanTell 2015-03-07
  • 打赏
  • 举报
回复
引用 5 楼 n7zj0x8 的回复:
[quote=引用 4 楼 YouNeverCanTell 的回复:] 主线程基本是一样的代码。能帮忙看一下吗,多谢!
差点凌乱了..这混合编程用得....目测你的问题应该是混合编程引起的 我给你贴一个处理了write函数的QTcpSocket,这个socket被我移动到一个单独的线程里面去了,但它write函数是线程安全的. 如果你有什么其它的函数接口需要调用m_pQTcpSocket的,像我那样写一个信号一个槽,然后连接起来,间接调用...这样可以保证m_pQTcpSocket在一个线程里面被使用. 这里问题来了,你可能会觉得这样写很麻烦或者不习惯.这个没有办法.如果你要用windows线程或者编程思想,处理Qt 的东西,真的会很纠结.. 貌似QTcpSocket在不同的Qt线程里面,调用它会报错(QSocketNotifier: socket notifiers cannot be enabled from another thread)..这里你的为什么没有报错,我估计就是因为你是windows的线程原因..不知道我有没有说错. 这里要么你使用windows的socket要么你使用Qt的线程..如果使用Qt的线程,又要说一堆...这个问题就真的复杂起来了....我只能帮你到这里了.

#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H

#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include <QHostAddress>

class MyTcpSocket : public QThread
{
    Q_OBJECT
public:
    MyTcpSocket()
        : m_pQTcpSocket(new QTcpSocket())
    {
        this->start();
        this->moveToThread(this);
        m_pQTcpSocket->moveToThread(this);

        connect(this, SIGNAL(DoMyWrite(QByteArray)),
                this, SLOT(OnMyWrite(QByteArray)));
        connect(this, SIGNAL(DoMyConnect()),
                this, SLOT(OnMyConnectToHost()));
    }

    ~MyTcpSocket()
    {
        this->exit();
        this->wait(10 * 1000);
    }

    void myWrite(const char *data, qint64 len)
    {
        emit DoMyWrite(QByteArray(data, len));
    }

    void myConnectToHost()
    {
        emit DoMyConnect();
    }

signals:
    void DoMyWrite(const QByteArray &data);
    void DoMyConnect();

private slots:
    void OnMyWrite(const QByteArray &data)
    {
        qDebug() << "write" << QThread::currentThreadId();
        m_pQTcpSocket->write(data);
        m_pQTcpSocket->flush();
    }
    void OnMyConnectToHost()
    {
        qDebug() << "myConnect" << QThread::currentThreadId();
        m_pQTcpSocket->connectToHost(QHostAddress::LocalHost, 8811);
    }

private:
    QTcpSocket * const m_pQTcpSocket;
};

#endif // MYTCPSOCKET_H

[/quote] 谢谢,改用定时器确实不会有这问题了。
大卫无限 2015-02-04
  • 打赏
  • 举报
回复
引用 4 楼 YouNeverCanTell 的回复:
主线程基本是一样的代码。能帮忙看一下吗,多谢!
差点凌乱了..这混合编程用得....目测你的问题应该是混合编程引起的 我给你贴一个处理了write函数的QTcpSocket,这个socket被我移动到一个单独的线程里面去了,但它write函数是线程安全的. 如果你有什么其它的函数接口需要调用m_pQTcpSocket的,像我那样写一个信号一个槽,然后连接起来,间接调用...这样可以保证m_pQTcpSocket在一个线程里面被使用. 这里问题来了,你可能会觉得这样写很麻烦或者不习惯.这个没有办法.如果你要用windows线程或者编程思想,处理Qt 的东西,真的会很纠结.. 貌似QTcpSocket在不同的Qt线程里面,调用它会报错(QSocketNotifier: socket notifiers cannot be enabled from another thread)..这里你的为什么没有报错,我估计就是因为你是windows的线程原因..不知道我有没有说错. 这里要么你使用windows的socket要么你使用Qt的线程..如果使用Qt的线程,又要说一堆...这个问题就真的复杂起来了....我只能帮你到这里了.

#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H

#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include <QHostAddress>

class MyTcpSocket : public QThread
{
    Q_OBJECT
public:
    MyTcpSocket()
        : m_pQTcpSocket(new QTcpSocket())
    {
        this->start();
        this->moveToThread(this);
        m_pQTcpSocket->moveToThread(this);

        connect(this, SIGNAL(DoMyWrite(QByteArray)),
                this, SLOT(OnMyWrite(QByteArray)));
        connect(this, SIGNAL(DoMyConnect()),
                this, SLOT(OnMyConnectToHost()));
    }

    ~MyTcpSocket()
    {
        this->exit();
        this->wait(10 * 1000);
    }

    void myWrite(const char *data, qint64 len)
    {
        emit DoMyWrite(QByteArray(data, len));
    }

    void myConnectToHost()
    {
        emit DoMyConnect();
    }

signals:
    void DoMyWrite(const QByteArray &data);
    void DoMyConnect();

private slots:
    void OnMyWrite(const QByteArray &data)
    {
        qDebug() << "write" << QThread::currentThreadId();
        m_pQTcpSocket->write(data);
        m_pQTcpSocket->flush();
    }
    void OnMyConnectToHost()
    {
        qDebug() << "myConnect" << QThread::currentThreadId();
        m_pQTcpSocket->connectToHost(QHostAddress::LocalHost, 8811);
    }

private:
    QTcpSocket * const m_pQTcpSocket;
};

#endif // MYTCPSOCKET_H

YouNeverCanTell 2015-02-04
  • 打赏
  • 举报
回复
引用 3 楼 n7zj0x8 的回复:
哎...我猜我肯定解释不清楚,如果你贴代码,到可以看下. socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作. 还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
线程是用Windows的API创建的

QTcpSocket* g_tcpSocket = new QTcpSocket();
HANDLE g_handleHeartBeat = CreateThread(NULL, 0, RunHeartBeat, g_Client, 0, NULL); // 创建心跳线程
DWORD WINAPI RunHeartBeat(LPVOID param)
{
    WaitForSingleObject(g_hMutex, INFINITE);
    Request request; // 需要向服务端发送的内容
    //.....填写request
    int nleft, nbytes;
    char* ptr = (char*)&request;

    nleft = 12;  // 需要发送的长度
     
    for (; nleft  > 0; )
    {
        nbytes = g_tcpSocket->write(ptr, nleft);
        g_tcpSocket->flush();     // 注释掉这行以后release版本就稳定了,但是debug版本不会及时发出消息

        if (nbytes <= 0)
        {
                // .......
                 ReleaseMutex(g_hMutex);
                return -1;
        }
        nleft -= nbytes;
        ptr += nbytes;
    }
    ReleaseMutex(g_hMutex);
}
主线程基本是一样的代码。能帮忙看一下吗,多谢!
大卫无限 2015-02-04
  • 打赏
  • 举报
回复
哎...我猜我肯定解释不清楚,如果你贴代码,到可以看下. socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作. 还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
YouNeverCanTell 2015-02-04
  • 打赏
  • 举报
回复
引用 1 楼 n7zj0x8 的回复:
flush不可能会让它不稳定的,这个你要绝对相信的. 这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
可能flush不是引起问题的真正原因,但是注释掉以后确实变得稳定了。我在使用socket时做了互斥,我们的框架设计是登陆和心跳一定要使用同一个socket。
大卫无限 2015-02-04
  • 打赏
  • 举报
回复
flush不可能会让它不稳定的,这个你要绝对相信的. 这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
这个是完整源码 java实现 大数据 Spark 可视化大屏+Kafka+SpringBoot+Vue3 【大数据毕业设计】基于Spark实时电商用户行为分析与预测(Java版本+可视化大屏+Kafka+SpringBoot+Vue3) 源码+论文 完整版 数据库Mysql 随着电子商务行业的快速发展,平台每天都会产生海量的用户行为数据,包括浏览、加购、收藏和购买等。如何对这些行为数据进行实时采集、高效统计与科学预测,已成为电商运营决策和智能推荐的关键问题。传统的离线批处理方式存在延迟高、反馈慢、难以支撑实时运营的不足,因此构建一套面向实时场景的电商用户行为分析与预测系统具有重要的工程意义和应用价值。 本文设计并实现了基于 Spark 的实时电商用户行为分析与预测系统。系统采用前后端分离架构,后端以 Java 与 Spring Boot 为核心构建 REST 接口服务,结合 Apache Kafka 完成行为事件的异步投递与缓冲,利用 Spark MLlib 对窗口销售额进行线性回归预测,并将结果持久化至 MySQL;前端基于 Vue3、Element Plus 与 ECharts 实现管理后台与可视化大屏。系统主要功能包括管理员登录与个人心、数据概览、行为数据查询、商品管理、实时统计、销售额预测以及可视化大屏展示。 在数据分析方面,系统通过行为模拟器持续生成 pv、cart、fav、buy 四类行为事件,按时间窗口聚合 PV、UV、加购数、收藏数、购买数和销售额等指标;在预测方面,采用滞后特征与小时特征构建训练集,优先使用 Spark 线性回归模型,并在异常情况下自动降级为 Java OLS 回归,保证服务可用性。测试结果表明,系统能够稳定完成实时统计与预测展示,界面交互清晰,能够满足本科毕业设计对完整性、可用性和技术综合性的要求。
YOLOv11公交车内紧急按钮目标检测数据集 目标类别:['Bus', 'Door', 'Handle', 'bell', 'chair', 'person'] 文类别:['公交车', '门', '扶手', '紧急按钮', '座椅', '乘客'] 训练集:6027 张 验证集:134 张 测试集:40 张 总计:6201 张 该数据集提供了data.yaml文件,内容如下: train: ../train/images val: ../valid/images test: ../test/images nc: 6 names: ['Bus', 'Door', 'Handle', 'bell', 'chair', 'person'] 该数据集聚焦于城市公共交通场景,针对公交车内部环境的紧急按钮进行精准标注与识别,具备高度的现实应用价值。通过多角度、多光照条件下的图像采集,全面覆盖了实际运营可能出现的各类紧急按钮形态与安装位置,为提升公共交通安全监控系统的智能化水平提供了坚实的数据支撑。 该数据集包含6027张训练图像、134张验证图像和40张测试图像,总量达6201张,分布结构合理,能够有效支持模型的训练、调优与性能评估。训练集规模充足,确保模型具备良好的泛化能力;验证集与测试集虽相对较小,但样本具有代表性,可准确反映模型在真实场景下的表现稳定性。 标注工作严格按照标准执行,所有目标均以绿色边界框清晰标出,标注位置精确,边界紧贴目标边缘,未出现明显偏移或遗漏现象。各类别区分明确,尤其对“紧急按钮”这一核心目标的标注一致性高,充分体现了高质量的标注规范性与专业性。 该数据集适用于智能交通、城市公交系统升级、公共安全监控等多个领域,可广泛应用于公交车内的异常行为识别、紧急事件自动报警、乘客安全辅助系统等智能化解决方案,助力构建更安全、高效的公共交通环境。共备交高通度环的境
内容概要:本文聚焦于含分布式电源的配电网可靠性评估研究,系统性地介绍了基于Matlab的仿真建模与代码实现方法,涵盖序贯蒙特卡洛模拟、分布式电源接入建模、配电网故障分析、网络重构及供电恢复策略等核心技术。研究通过构建典型配电系统模型,模拟多种故障场景,结合可靠性指标(如SAIDI、SAIFI、ASAI等)进行定量评估,并深入探讨分布式电源(如光伏、风电、储能)对系统可靠性的影响机制。资源包提供了完整的Matlab代码、Simulink仿真模型及相关算法实现,支持用户复现经典案例并开展拓展研究,适用于电力系统规划、运行与可靠性分析等领域。; 适合人群:具备电力系统分析基础和Matlab编程能力的研究生、科研人员及电力工程技术人员,特别适用于从事智能配电网、分布式能源接入、微电网可靠性等方向研究的专业人士。; 使用场景及目标:① 掌握配电网可靠性评估的理论体系与仿真流程;② 利用Matlab实现含分布式电源的配电网故障模拟与可靠性指标计算;③ 复现高水平论文的可靠性分析模型与算法,提升科研复现与创新能力;④ 为学位论文、科研项目或工程实践提供可靠的技术支撑与代码参考。; 阅读建议:建议读者结合提供的网盘资源,按照“基础理论→潮流计算→故障模拟→可靠性评估”的顺序循序渐进学习,优先掌握蒙特卡洛模拟与故障隔离恢复逻辑,再深入分布式电源建模与指标统计分析。学习过程应动手调试代码,对比不同渗透率、不同接入位置下的仿真结果,强化理论与实践的深度融合。
内容概要:本文系统研究了基于蜣螂优化算法(DBO)的无线传感器网络(WSN)覆盖优化问题,提出了一种利用生物启发式智能算法提升WSN空间覆盖率的有效方法。通过构建合理的数学模型,将传感器节点部署问题转化为多维函数优化问题,并采用Matlab平台进行仿真实验,验证了DBO算法在不同规模和环境下的优化性能。研究重点分析了DBO算法的搜索机制、收敛特性及其在避免局部最优方面的优势,同时与粒子群优化(PSO)、灰狼优化(GWO)等主流智能算法进行了对比实验,结果表明DBO在覆盖均匀性、收敛速度和全局寻优能力方面表现更为优越,显著提升了网络的整体感知效能和资源利用率。; 适合人群:具备一定智能优化算法基础,从事无线传感器网络、物联网、自动化或相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①解决无线传感器网络因节点分布不均导致的覆盖盲区与重叠冗余问题;②提升WSN在环境监测、智慧农业、城市安防等实际应用的监测精度与系统可靠性;③为智能优化算法在复杂工程布局与资源配置问题的应用提供可复现的技术范例与研究参考。; 阅读建议:建议读者结合提供的Matlab代码深入理解DBO算法的实现细节与参数调优策略,通过动手实践掌握算法移植与改进方法,并可进一步拓展至路径规划、多目标优化等相关领域开展创新性研究。

21,499

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧