ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 概述 示例 ``` struct UDPPacker { quint16 m_srcPort; //源端口 quint16 m_dstPort; //目的端口 quint16 m_length; //UDP头部和报文总长度 quint16 m_checksum; //校验和(不是强制要求) QByteArray m_data; //报文内容 //友元声明,一对用于支持QDataStream 输入输出的函数 // 方式一:先声明,在 cpp 中实现 // friend QDataStream & operator<<(QDataStream & stream, const UDPPacker & udp) // friend QDataStream & operator>>(QDataStream & stream, UDPPacker & udp) // 方式二:直接在结构体中实现 friend QDataStream & operator<<(QDataStream & stream, const UDPPacker & udp) { //将数据按照规定顺序都写入流中,整型数值会自动转为网络字节序 stream<<udp.m_srcPort; stream<<udp.m_dstPort; stream<<udp.m_length; stream<<udp.m_checksum; //写入裸的数据报文 stream.writeRawData( udp.m_data.data(), udp.m_data.size() ); //返回数据流对象 return stream; } friend QDataStream & operator>>(QDataStream & stream, UDPPacker & udp) { //按照原来的顺序和类型读取,网络字节序自动转为主机字节序 stream>>udp.m_srcPort; stream>>udp.m_dstPort; stream>>udp.m_length; stream>>udp.m_checksum; //读取裸的数据报文 //readRawData参数的缓冲区必须由程序员提前分配空间 //计算报文消息的长度 int nMsgLen = udp.m_length - 8; //减去包头 8 字节 char *buff = new char[nMsgLen]; //分配空间 stream.readRawData( buff, nMsgLen ); //把数据读到缓冲区 //把缓冲区设置给 QByteArray 对象,缓冲区自动划归 QByteArray 对象管理,不要手动删除 buff 指针 udp.m_data.setRawData( buff, nMsgLen ); //返回数据流对象 return stream; } }; // 生成流 QByteArray baMsg("hello world"); UDPPacker udp; udp.m_srcPort = 0x11; udp.m_dstPort = 0x22; udp.m_length = 8 + quint16(baMsg.size()); //8是包头长度 udp.m_checksum = 0 ; //这里填充0,UDP校验和不是强制要求 udp.m_data = baMsg; QByteArray bytes; QDataStream stream(&bytes,QIODevice::ReadWrite); // udp 写入流 stream<<udp; qDebug()<<bytes.toHex(); // 读出流 QDataStream stream1(bytes); UDPPacker udp1; stream1>>udp1; qDebug()<<udp1.m_data; // "hello world" ``` 注意: 1. 声明友元类,是为了支持QDataStream的输入输出函数