十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Qt网络编程实战:TCP/UDP通信、粘包处理与跨平台部署指南

Qt网络编程实战:TCP/UDP通信、粘包处理与跨平台部署指南 很多做Qt上位机开发的工程师都有同感界面、绘图、串口这些模块资料一大堆唯独到了TCP/UDP网络通信这块总是看文档容易写起来却总是遇到莫名其妙的问题。比如客户要的TCP服务器同时挂几十个设备比如UDP收发的字节序处理再比如Linux下Qt程序部署到客户机器上后端口连不上。这篇文章就是我做了多个Qt网络项目后的实战沉淀从环境准备、基础Demo到粘包处理、心跳保活、多线程收发再到我用过的调试工具和踩过的坑一次性把手上的干货整理出来希望对正在做或者准备做Qt网络开发的朋友有用。1. 为什么Qt网络编程值得专门研究先用一句话总结Qt对网络通信的封装能做到让你不用关心操作系统差异但前提是你得理解它封装背后的机制。很多人觉得Qt的TcpSocket/QUdpSocket就是把系统socket包了一层用起来简单但实际上踩坑的地方全在封装这两个字上。以我做过的项目为例一套设备采集系统Windows开发机上跑得一切正常到了客户现场Linux工控机上TCP客户端连不上服务器。最后排查下来不是代码逻辑问题是Qt版本默认的socket后端以及系统防火墙对端口的策略不一样。这种问题如果不理解Qt网络模块的工作机制光看报错信息很难定位。另一个让我觉得值得专门研究的原因是Qt网络模块在国产化环境下的表现。现在很多项目要求运行在统信UOS、麒麟等Linux发行版上Qt的网络模块在不同发行版上依赖的底层库有差异静态编译和动态编译也有不同的坑。如果只是照着Windows上的教程写部署阶段会很被动。所以这篇文章覆盖的内容既包括纯粹的Qt TCP/UDP编程技巧也包含跨平台部署和调试的经验。阅读本文的前提是你已经下载好Qt并创建过普通Widgets项目不需要精通C但至少能看懂类的基本用法。没有下载好的也不用着急后面我会先讲环境准备。2. 环境准备与项目配置找准姿势再动手Qt网络编程不需要额外的库Qt Network模块在默认安装时就有。我做过的项目里最难的反而是环境不对导致编译失败——经常遇到有人问为什么我include了QTcpSocket却报no such file。2.1 版本选择和编译器匹配是第一个坑从我的实践看Qt 5.15.2和Qt 5.14.2是最适合做网络通信项目的版本。为什么不是Qt 6因为Qt 6在嵌入式设备、工控机上的生态兼容还有历史包袱要背很多第三方硬件SDK至今还是For Qt5的。而5.14和5.15之间我优先推荐5.15.2因为它是5.x系列最后维护周期很长的LTS版本bug修复更充分。第二个坑是编译器套件。打开Qt Creator时会看到Desktop Qt 5.15.2 MinGW 64-bit、Desktop Qt 5.15.2 MSVC2019 64-bit这样的选项。做TCP/UDP这类网络程序官方开放的MinGW套件通常比MSVC更方便因为它不需要额外装Visual Studio编译出的exe在目标机器上部署时也不需要装VC运行库。但如果你要跟其他MSVC编译的第三方库混用那就只能选MSVC套件。在.pro或者CMakeLists.txt里要主动加上network模块:QT core gui networkfind_package(Qt5 COMPONENTS Core Gui Network REQUIRED) target_link_libraries(your_project Qt5::Core Qt5::Gui Qt5::Network)2.2 Linux部署时最容易忽略的套接字相关配置很多人代码在Windows上跑通打包到Linux工控机上就各种连不上。除了常见的防火墙问题还有一种情况是部署机器上缺少xcb相关的运行库导致程序根本起不来——这在纯网络项目中容易被忽略因为程序崩溃日志往往不直接提示是网络问题。简单记录一下我在Linux下部署网络程序前的排查步骤确认程序能正常启动并显示界面确认目标端口没有被占用netstat -tunlp | grep 端口号设置防火墙放行端口以CentOS/Rocky为例firewall-cmd --zonepublic --add-port8080/tcp --permanent firewall-cmd --reload如果使用UDP通信端口放行同理把tcp换成udp。另外还有一个低级但常见的错误Qt程序里如果用QHostAddress::LocalHost连接本机服务端这没有任何问题但如果部署后程序运行在别的机器上就要改成具体的IP地址——或者在界面里留一个服务器IP/端口配置项。这点看起来简单但我在不少项目里见到有人把本机调试地址硬编码在代码里导致一到现场就抓瞎。2.3 串口模块报错与Qt网络项目相关的连锁配置问题热搜词里出现了Qt unknown module in qt:serialport这个问题虽然看起来和网络编程无关但实际上很常见很多设备类项目是串口网络双通道通信的串口收数据转换后走TCP上报。如果你遇到unknown module(s) in qt: serialport说明安装Qt时没有勾选SerialPort模块。这个问题我的解决方式是Windows下打开Qt Maintenance Tool勾选对应版本的SerialPort模块更新安装Linux下如果直接从源码编译或者通过包管理器安装需要额外安装libqt5serialport5-dev之类的开发包如果是采用离线安装包需要提前确认安装组件清单里包含你要用的所有模块。之所以特意说这个是因为它的排查思路跟Qt网络编程的环境准备一脉相承先确认模块存在再谈代码。我在新电脑上配置Qt环境时会先写一个三行的测试代码分别includeQTcpSocket、QUdpSocket和QSerialPort编译通过后再进入正式开发这个习惯帮我省了很多时间。3. TCP知识扫盲三次握手、四次挥手、长短连接怎么选写Qt前需要先把TCP本身的一些关键概念理清楚代码只是工具传输协议本身的模式决定了代码怎么写。3.1 三次握手和为什么客户端能瞬间连接失败TCP建立连接的三次握手用代码来理解就是客户端connectToHost()数据包发出SYN服务端回复SYNACK客户端再回ACK然后连接建立。这三步是Qt已经帮我们做完的。你不需要手动处理握手但必须理解它的表现。我们经常遇到的一个场景是客户端连接一个不存在的IP或者被防火墙丢弃SYN的IP界面上会卡很久然后才报连接失败。为什么因为connectToHost()是异步的底层SYN包发出后在没有收到响应时会不断重试。Qt默认超时机制在底层socket里应用层感知到的卡顿其实是TCP在重传。从工程角度我建议在调用connectToHost()前先设置setSocketOption(QAbstractSocket::LowDelayOption, 1)再配合定时器在超过设定时间后强制abort()。核心代码如下socket-connectToHost(host, port); if (!socket-waitForConnected(3000)) { socket-abort(); // 这里做失败处理 }注意waitForConnected()会阻塞当前线程如果在界面线程调用界面会卡死。正确做法是在工作线程里使用等待或者纯靠connected()信号回调。3.2 四次挥手与ConnectionReset问题四次挥手对应代码里就是调用disconnectFromHost()后TCP会走完FIN/ACK的交互流程。但我在实际项目里更常遇到的是另一方直接断电、拔网线、进程强制杀掉的场景这时候TCP没有机会走四次挥手。这时候如果你读数据就会遇到QAbstractSocket::RemoteHostClosedError或者底层提示Connection reset by peer。这个错误的本意是对端主机给你回了RST包连接已经异常终止。写网络程序不需要纠结为什么每次都会出现但你要知道怎么处理捕获error()信号对RemoteHostClosedError做资源清理和重连。我自己的处理模板是connect(socket, QTcpSocket::disconnected, this, [this](){ if (socket-state() ! QAbstractSocket::UnconnectedState) { socket-disconnectFromHost(); } socket-deleteLater(); socket nullptr; // 重连逻辑 });3.3 长连接和短连接的实际选择从热搜词里能看到很多人搜tcp长连接与短连接。我给予的实际建议非常简单请求响应模式客户端主动发一条、服务端回一条使用短连接即可代码简单服务端不易资源泄漏设备数据上报/远程控制/聊天必须长连接因为要服务端主动推消息。在Qt里做长连接必须写心跳机制。TCP本身有Keep-Alive但默认两小时才探测一次基本不可用。我在项目里通常使用30秒到60秒的定时器往服务端发一个自定义的心跳包比如一个JSON字符串或者两个字节如果在两个周期内没有收到任何数据判定连接失效后就主动重连。心跳包不是TCP保活它是应用层协议的一部分。这个区别必须明确。4. Qt TCP实战从单客户端到多客户端管理的完整链路这一节写一个能用的TCP服务端和客户端Demo并重点讲讲我用Qt做多客户端管理时的设计。4.1 先写一个能跑的最小服务端用Qt写TCP服务端很简单QTcpServer负责监听nextPendingConnection()取出新连接。最小示例// server.h class TcpServer : public QObject { Q_OBJECT public: TcpServer(quint16 port) { server new QTcpServer(this); connect(server, QTcpServer::newConnection, this, TcpServer::onNewConnection); server-listen(QHostAddress::Any, port); } private slots: void onNewConnection() { QTcpSocket* client server-nextPendingConnection(); connect(client, QTcpSocket::readyRead, this, [client]() { QByteArray data client-readAll(); // 处理收到数据 }); connect(client, QTcpSocket::disconnected, client, QTcpSocket::deleteLater); } private: QTcpServer* server; };这个Demo跑通没问题但有一个非常隐蔽的坑nextPendingConnection()返回的QTcpSocket如果只在局部变量里保存而不在类里管理会被垃圾回收或者指针悬挂。务必把client指针存在一个容器里比如QListQTcpSocket*或者QHashQTcpSocket*, ClientInfo。4.2 处理粘包不是Qt的问题是TCP流式传输的必然很多人第一次调通收发后发现客户端发了Hello和World服务端readAll()一次性读到HelloWorld这就是粘包。TCP是字节流协议它不保证消息边界只保证字节顺序和可靠性。要解决粘包必须自己定义协议框架。我常用的方式有两种方式一长度前缀法。发送前先封装前4字节是小端或大端表示的负载长度后面跟着负载数据。接收方先读4字节算长度再读对应数量的数据构成一个完整的消息。方式二分隔符法。在消息末尾加一个特定的结束标记比如\r\n或\0。这种方式适合JSON文本协议但注意负载里不能出现同样的分隔符。我在实际项目中更偏好长度前缀法因为二进制效率高且不污染内容。接线示意如下// 发送端封装 QByteArray payload hello; QByteArray block; QDataStream out(block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_15); out (quint16)payload.size(); block.append(payload); socket-write(block);接收端用QDataStream配合quint16就能完成读长度再继续读负载。QDataStream默认用大端序协议两端最好都是Qt程序如果是跟其他语言通信要约定好字节序。4.3 多客户端管理用哈希表维护连接状态当服务端需要同时管理多个客户端时推荐使用QHashQTcpSocket*, QByteArray做缓冲每个socket对应自己的接收缓冲区这样天然按连接隔离数据。完整的接收缓冲区函数void TcpServer::onReadyRead(QTcpSocket* client) { QByteArray buffer buffers[client]; buffer.append(client-readAll()); // 每次读完检查有没有完整的包 while (buffer.size() 2) { quint16 len (quint16)((unsigned char)buffer[0] 8) (unsigned char)buffer[1]; if (buffer.size() 2 len) return; QByteArray payload buffer.mid(2, len); buffer.remove(0, 2 len); processPayload(client, payload); } }这里我把几个关键点放一起讲用readAll()一次性取出所有可读数据但不要让readAll()频繁触发大内存拷贝缓冲区保持在合理范围处理完及时移除不要把业务逻辑放在readyRead信号里做太多耗时处理一般我都是解析出完整包后QMetaObject::invokeMethod抛到工作线程客户端断开时要清理缓冲区记录否则QHash里残留垃圾数据。4.4 也讲讲客户端这边的重连策略客户端比服务端简单但重连逻辑依然是核心。我们的上位机软件若当客户端通常要保证TCP断线后自动重连重连时不能导致界面卡顿。我习惯用一个QTimer来做重连判断QTimer* reconnectTimer new QTimer(this); reconnectTimer-setInterval(3000); connect(reconnectTimer, QTimer::timeout, this, [this](){ if (socket-state() QAbstractSocket::UnconnectedState) { socket-connectToHost(serverIp, serverPort); } }); reconnectTimer-start();另外要小心的一点连接状态为ConnectingState时就不要重复发起connectToHost了否则会重复触发错误处理。设置一个标志位if (socket-state() QAbstractSocket::UnconnectedState) { socket-connectToHost(serverIp, serverPort); isManualClose false; }4.5 实际对接中遇到的S7-1200与Modbus TCP热搜词里出现了s7-1200与4台modbus tcp轮询和modbus tcp server测试工具。这类PLC上位机的项目本质就是TCP客户端按Modbus协议帧格式做轮询。Qt里没有官方Modbus库需要用QTcpSocket自己拼Modbus TCP报文。Modbus TCP协议和普通TCP最大的不同是报文有固定结构——事务标识符、协议标识符、长度、单元标识符、功能码、数据。在写代码时注意两点事务标识符要自增用于匹配请求和响应如果同时轮询多台设备建议串行发送发完一帧等响应超时后再处理下一台设备。我用4台PLC做过测试如果并发发报文一旦设备响应顺序错位匹配逻辑就会很混乱。虽然可以用事务ID去匹配但工程上为了可靠性串行轮询是最稳的。我在实现这类工具时经常需要Modbus TCP Server测试工具这时候如果不想用第三方软件可以自己用Qt写一个模拟Server绑定502端口监听请求并回响应这对验证客户端软件的轮询逻辑非常有帮助。5. Qt UDP实战广播、组播与原始套接字边界TCP讲完来说说UDP。UDP给大多数人的第一印象是简单、不可靠、速度快但真正做Qt UDP实战时才发现坑一点也不比TCP少。5.1 QUdpSocket的基本收发与为什么收不到数据最基础的一段绑定udpSocket new QUdpSocket(this); udpSocket-bind(port, QUdpSocket::ShareAddress); connect(udpSocket, QUdpSocket::readyRead, this, [this](){ while (udpSocket-hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket-pendingDatagramSize()); QHostAddress sender; quint16 senderPort; udpSocket-readDatagram(datagram.data(), datagram.size(), sender, senderPort); // 处理 } });这里容易踩的第一个坑是不bind直接connectToHost发数据可以但直接readDatagram收不到数据。UDP的bind决定了套接字监听哪个本地端口只有bind后才能接收发往该端口的数据报。第二个坑pendingDatagramSize()返回的是当前第一个数据报的大小如果缓冲区里堆积了好几个数据报别的语言可能一次取完但Qt这里要用while循环。很多新手只readDatagram一次导致数据丢失。5.2 组播的正确打开方式组播最典型的应用场景是局域网设备发现。比如电脑上运行Qt工具在局域网内查找设备设备上电后加入同一组播组电脑发送组播请求设备回应自己的IP和序列号。Qt里组播的核心API只有两个joinMulticastGroup()和leaveMulticastGroup()。但实际开发中我多次遇到局域网里有些机器能收到组播、有些收不到的问题原因基本出在这几点bind的端口和组播端口不一致加入组播组的套接字要先bind到组播端口网卡策略Windows上如果开了多个网卡或者虚拟网卡VMware、VirtualBox发送组播时可能走了错误的网卡。解决办法是setMulticastInterface指定网卡路由器隔离一般办公网的交换机默认是支持组播转发的但有些安全策略会隔离组播报遇到这种环境排查时要先用Wireshark抓包确认报文是否到达本机而不是直接怀疑Qt代码。一个可靠的最小组播接收例子udpSocket-bind(QHostAddress::AnyIPv4, 45678, QUdpSocket::ShareAddress); udpSocket-joinMulticastGroup(QHostAddress(239.255.43.21));发送端udpSocket-writeDatagram(data, QHostAddress(239.255.43.21), 45678);发组播的前提是路由表里有组播路由同一台机器多网卡时需要重点看setMulticastInterface。5.3 UDP协议栈里的测试工具和大包问题热搜词里有eventgroup udp 测试和iperf3使用udp打流这个场景我也遇到过。用UDP做高吞吐测试时瓶颈往往不在Qt而在操作系统UDP缓冲区。Linux下默认UDP接收缓冲区较小高流量下会丢包。如果Qt程序需要长时间大流量接收UDP建议把socket接收缓冲区调大udpSocket-setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 4 * 1024 * 1024);另一个问题是UDP大包被分片/丢弃的风险。以太网MTU是1500字节扣掉IP和UDP头之后数据报超过1472字节就有分片风险。实际在跨路由器场景下大包经常被静默丢弃。应用层自我约束UDP单包不要超过1400字节这是很廉价却很有效的稳妥方案。5.4 多线程下的UDP别在槽函数里做解码UDP的readyRead信号触发频率比TCP更高因为每条数据报都会触发一次。如果你把加密解密、业务解析直接放在槽函数里高负载时UI线程会被拖垮。我用过的优化方式读数据报的线程和业务处理线程分离。读线程只做一件事——把原始QByteArray放进线程安全的队列处理线程取出后做解析。Qt的QQueue加QMutex或者直接用QSharedPointer的消息队列都能实现。如果你的项目用的是Qt 5.10以上也可以考虑QThreadPool配合QRunnable但注意控制并发数量别每条数据报开一个线程。6. 网络调试与排错我在实测中踩过的坑这是真正值钱的一部分。无论TCP还是UDP你做完了是不是就万事大吉并不是。我在多个项目中遇到过的常见问题整理如下。6.1 bind: Address already in useWindows下启动服务端程序时偶尔会报bind: Address already in use。第一次遇到时我下意识觉得是端口被别的程序占了但查出PID后发现就是自己上一次程序残留的TIME_WAIT连接占用。解决方式有几种用ReuseAddressHint设置bind选项如server-listen(QHostAddress::Any, port)前先调用setSocketOption(QAbstractSocket::ReuseAddressHint, 1)极端情况下强制用SO_REUSEADDR但要注意在多进程场景下可能导致两个进程绑同一个端口不建议在生产环境随便用。如果你在Linux下还遇到Address already in use先用下面的命令确认lsof -i:8080 ss -tulpn | grep 80806.2 error: listen tcp 127.0.0.1:11434: bind: only one usage of each socket address这个报错是Windows Qt下常见的。大意是同一IP端口的二元组已经被占用。从实践看最常见的原因就是上一个调试实例没退出程序没有释放心柄。在Windows下可以用netstat -ano | findstr 11434查到占用进程结束之后重新启动程序就能恢复。如果是开发调试阶段反复出现可以设定端口时加一个偏移量或者用随机端口但真机部署时必须固定端口所以要习惯从进程管理维度去排查占用问题。6.3 curl: (35) tcp connection reset by peer与Qt程序的关系热搜词里出现curl的报错我觉得有必要说清楚TCP connection reset by peer含义是对端发RST。这种情况在Qt网络程序里多数不是Qt代码逻辑问题而是服务端程序收到了数据但主动调用了abort()或直接关闭了socket客户端往一个已经关闭的socket上写数据服务端进程崩溃内核代发RST。用Qt写服务端时尤其要避免在收到未知数据后直接abort()。更好的做法是如果协议校验失败先读取并丢弃或者记日志而不是立刻断开否则客户端报connection reset很难排查。6.4 防火墙与unknown module(s) in qt这类环境的混淆我在第2节提到过模块安装问题这里再补充一个真实经历客户在Linux上使用我发布的Qt程序日志里显示socket连接失败一开始排查防火墙放行了端口也没用。后来发现程序报错根本不是网络问题而是serialport模块缺失导致插件加载失败、程序主线程退出。这种情况常被当成网络问题排查因为程序没有正常启动界面一闪而过。解决办法就是在发布时用ldd检查依赖库完整性确保libQt5Network、libQt5SerialPort等动态库都打全或者干脆用Qt的windeployqt/linuxdeployqt工具来自动收集依赖。6.5 Qt事件循环与阻塞式网络调用另一个必须强调的坑在GUI线程里使用waitForConnected()、waitForReadyRead()会让界面卡死因为Qt是事件循环驱动的。如果你的代码里出现了这种调用多个UI事件都会阻塞整个程序表现得像死机一样。正确方案是一切网络事件都通过信号槽处理。所有耗时操作放到QtConcurrent或者自己new一个QThread。我就有过一次惨痛教训在按钮点击处理函数里写了waitForReadyRead(5000)等数据结果客户反馈点按钮就白屏后来才改成异步方式。6.6 判断连通性的实用命令和工具最后附带一个我常用的调试工具清单netstat/ss/lsof查端口占用telnet测TCP端口是否能连通Wireshark抓包看三次握手、RST、UDP包是否到达自己写一个Qt的调试Server/Client工具也很有帮助Linux下也可以用nc -ul 端口测UDP端口能否监听。如果别人问为什么我的Qt客户端连接不上我的第一句话永远是先用telnet IP 端口检测基础网络通不通排除掉网络本身的问题再来看代码这个顺序能节省一半时间。7. 压力测试与验证从能通到稳定代码能跑通只是第一步网络程序的值钱之处在稳定性。这里分享一下我做压力测试的方法和数据经验。7.1 用iperf3验证网络链路本身如果Qt程序出现丢包、速度慢先不要急着改代码。先用iperf3测一下链路本身的带宽和丢包率。命令很简单TCP打流iperf3 -s # 服务器端 iperf3 -c 192.168.1.100 -t 60UDP打流iperf3 -u -c 192.168.1.100 -b 100M -t 60如果iperf3测出来丢包率很高那说明是网络链路问题Qt代码再优化也白搭。如果链路很好但Qt程序丢包才需要从代码上找原因。7.2 我自己的Qt程序压测方案针对TCP服务端我通常这样测用脚本模拟100个客户端同时连接每个客户端每隔1秒发一条消息观察服务端是否存在内存增长、崩溃、句柄泄漏连续跑24小时检查日志是否出现异常断开。针对UDP接收我通常这样测用另一台机器连续发送100万条小包256字节Qt端统计接收次数、校验序号连续性观察是否出现pendingDatagramSize()为负数或者崩溃——出现负数是典型的调用错误一般是缓冲区读取逻辑写错了。7.3 从测试中得出的Qt编码建议压测暴露的问题往往能反向指导编码。我总结了几条不要在信号槽里写耗时循环、socket容器管理要严谨、缓冲区要限制最大长度防止恶意数据撑爆内存。后者很重要——如果协议里声明长度字段为65535实际发送者可以伪装成0xFFFFFFFF接收方就会分配巨大缓冲区导致内存耗尽。这类安全编码问题在工业现场设备上更要预防。7.4 跨平台差异Windows和Linux下的表现不同同一套Qt代码我在Windows和Linux下测试发现两个现象Linux下UDP接收高频小包时默认socket缓冲区被填满后新包会被内核丢弃这是正常现象调大ReceiveBufferSizeSocketOption即可Windows下的Qt程序如果以服务方式运行需要注意Session隔离端口不会冲突但防火墙弹窗规则需要在管理员权限下放行。如果你做的是嵌入式Linux设备Qt版本往往较老比如5.9/5.12时代。这些老版本的网络API和5.15相比差异不大但SSL库的链接方式差异大如果涉及TCPTLS链接建议先查一下自带SSL版本是否满足网站证书要求。8. 写个简单的TCP调试助手等于给自己打造一个利器跑通了上面的Demo结合你们自己的业务场景基本就能开工了。不过每次开发时都靠代码打印日志调试太痛苦我自己写了一个简单的TCP调试助手功能不复杂但省了很多事。界面大概就三块连接区输入IP/端口/连接按钮、发送区消息输入框/发送按钮/定时循环发送开关、接收区只读文本框/清空/保存到文件再加一个字符编码切换UTF-8/GBK。这个工具我几乎每天用。如果只是想找一个现成的TCP调试助手推荐用开源的SocketTool或者自己搜社区里的Qt开源项目。但我个人体会是自己写一个会得到完全够自己用的功能。更进一步你还可以在这个基础上扩展udp测试、modbus模拟服务端、组播测试等等。写这个工具时要注意一点接收区用QPlainTextEdit而不是QTextEdit因为当数据量大时前者性能明显好得多。高频接收时也不要先把所有内容都append到UI控件里先放队列每200ms刷新一次UI显示否则程序会卡顿。这个技巧在任意上位机项目里基本通用。9. 最后再分享几个实战体会如果让我用一句话来总结Qt网络编程API只是外衣协议设计和稳定策略才是核心。Qt已经把TCP/UDP变成了信号槽式的开发模式真正的难点在于理解TCP的流式特性、UDP的不可靠性、跨平台的环境差异。我自己在项目中反复用到的配套方案再列一遍供参考TCP长连接一定要心跳二进制数据一定定义长度前缀加版本号多包粘包用缓冲区增量解析GUI线程远离阻塞式调用不管TCP还是UDP异常处理路径永远要包含网络正常但数据异常的分支。每一个踩过坑的地方都是值得写进你们团队编码规范的点。希望这篇Qt TCP/UDP实战指南能帮你少走一些我走过的弯路。如果你们在做具体的网络模块集成或者遇到特定Device对接的问题欢迎在评论区分享你用的具体场景我看到之后会继续补充相关的实现细节。
返回列表