qudpsocket是qt中udp通信的核心类,需手动绑定端口(bind)才能接收数据,发送用writedatagram,接收需连接readyread信号并循环调用readdatagram处理每个独立数据报。

Qt 的 UDP 通信核心是 QUdpSocket,它不是“开箱即用”的可靠传输工具,而是轻量、无连接的底层封装——你得自己处理丢包、乱序、超时、数据边界等问题。
如何创建并绑定 QUdpSocket
UDP 不需要 connectToHost,关键在 bind():只有绑定了本地端口,才能收包;不绑定也能发包,但无法接收响应。
常见错误:bind() 失败却不检查返回值,导致后续 readyRead() 信号永不触发。
- 使用
QHostAddress::Any绑定所有网卡(IPv4 + IPv6 需分开或用QHostAddress::AnyIPv4) - 指定端口时注意权限:Linux/macOS 下 1024 以下端口需 root;Windows 通常无限制
- 若提示
"Address in use",说明端口被占用——可设QUdpSocket::ShareAddress标志允许多个 socket 共享(慎用,需配合QUdpSocket::ReuseAddressHint)
发送 UDP 数据包的正确写法
writeDatagram() 是唯一发送接口,但它不保证送达,也不阻塞等待确认。
容易忽略的点:
- 目标地址必须是有效的
QHostAddress,不能传字符串(如"127.0.0.1"),要用QHostAddress("127.0.0.1") - 端口号是
quint16类型,别传负数或超65535的值,否则静默失败 - 数据长度不能超过 65507 字节(IPv4 UDP 载荷上限),超长会被系统截断且不报错
- 建议检查返回值:
writeDatagram()返回实际写入字节数,≠ 传入长度就说明出错了
接收数据时怎么避免丢包和粘包
UDP 本身没有“粘包”概念——每个 writeDatagram() 对应一个独立数据报。所谓“粘包”其实是应用层误读:一次 readDatagram() 只取一个完整报文,但若缓冲区太小,会截断数据。
实操要点:
- 始终先调用
pendingDatagramSize()获取当前待读报文长度,再分配足够 buffer - 用
readDatagram(buf.data(), buf.size(), &sender, &senderPort)同步读取,并获取来源地址和端口(响应时必需) - 不要在
readyRead()槽函数里只读一次——网络可能堆积多个报文,应循环读直到hasPendingDatagrams()返回 false - 如果收不到包,先用
netstat -u -n(Linux)或Get-NetUDPEndpoint(PowerShell)确认 socket 确实 bind 成功且端口监听中
跨平台与防火墙注意事项
Windows 上默认防火墙会拦截 UDP 入站流量,即使程序是本机自测也会失败;macOS 的“防火墙选项→阻止所有传入连接”也会屏蔽 UDP。
调试阶段建议:
- 用
nc -u 127.0.0.1 8080(Linux/macOS)或Test-NetConnection -ComputerName 127.0.0.1 -Port 8080 -Udp(PowerShell)验证端口可达性 - Qt Creator 运行时若提示
"Network unreachable",大概率是QHostAddress构造失败(比如域名解析失败却没判空) - Android/iOS 需额外申请网络权限(
android.permission.INTERNET),且部分厂商 ROM 会主动限速或丢弃小 UDP 包
UDP 的简单性是假象,真正难的是设计合理的应用层协议:怎么标定消息头、怎么分片重组、怎么探测对方存活、怎么应对 NAT 穿透……QUdpSocket 只负责把字节扔进网卡,剩下的全得你自己兜住。











