在学习QT的过程,客户端/服务端 收发自定义复杂数据包(结构体带指针的不定长数据)的处理
示例如下,首先在头文件中申明这个自定义结构体(收发部分都需要包含这个结构体定义)
其中char pValue[0]表示这个是变长的部分!!!
#pragma pack(1)
struct DHPacket
{
int len;
char pValue[0];
};
#pragma pack()
一定要记得#pragma pack(1)【copy 一段别人的解释 :) (在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。)】
在发送端,组织代码,进行包装,即
DHPacket* dhPacket = new DHPacket();
dhPacket->len = len;//把真实的数据长度放在这个dhPacket的成员变量len里(PS:这个真实数据指的是实际放在char pValue[0]里面的内容)
接着申请长度为这个sizeof(DHPacket)+len的char* allData数据,
并将其前【0~sizeof(DHPacket)-1】的内容填充为dhPacket的值;
接着将其【sizeof(DHPacket)~sizeof(DHPacket)+len-1】的值填充为真实的数据
这样就可以将其系列化的数据发送出去
QString info;
info = lineEdit->text();
info += "\0";
if(info.length() > 0)
{//有数据
//自己定义DHPacket 组装发送给客户端
const char* data = info.toStdString().data();
int len = strlen(data);
int packetSize = sizeof (DHPacket);
DHPacket* dhPacket = new DHPacket();
dhPacket->len = len;
char* allData = new char[sizeof(DHPacket)+len];
memcpy(allData,(char*)dhPacket,sizeof(DHPacket));
memcpy(allData+sizeof (DHPacket),data,len);
if(udpSocket->writeDatagram(
allData,sizeof(DHPacket)+len,QHostAddress::Broadcast,portID)
!= sizeof(DHPacket)+len)
{
QMessageBox::information(this,"提示",
QString("%1 广播失败").arg(info));
}
free(allData);
}