UDP传送和接受结构体结构的消息 您所在的位置:网站首页 qt序列化结构体 UDP传送和接受结构体结构的消息

UDP传送和接受结构体结构的消息

2024-07-13 16:24| 来源: 网络整理| 查看: 265

前言

    最近的项目用到UDP接收结构体,以为和普通的传送字符串的一样,没想到我还是太天真。要能够接收或者传送结构体,一个很重要的知识点是:结构体字节对齐。废话不多说,小课堂开始了!

结构体对齐

参考https://www.cnblogs.com/codingnutter/p/5634482.html

    许多计算机系统对基本数据类型合法的进行了一些限制,要求某种类型对象的地址必须是某个值(通常是2,4 和8)的倍数。这种对齐简化了形成处理器与存储系统之间的接口的硬件设计。当数据结构为结构体时,为了满足这种数据对齐的机制,编译器可能需要在结构体的字段的分配中插入间隙--向结构体中最大的元素对齐。

typedef struct { char c; int i[2]; double v; }S;

    看上面的结构体,在没有数据对齐的情况下,size()=1+4*2+8=17字节。

    再编译器数据对齐处理后,他的结构大小变成了24字节(向结构体中最大的元素对齐),内存布局为

这个就是为什么我强转后,结构体中的部分数据是乱码的。

 改进后(结构体一字节对齐)

在听取网友意见后,发现将结构体一字节对齐后,操作真的是非常简单。

结构体一字节对齐:

#pragma pack(1) //指定一字节对齐 struct Test_data{ int iNumber; char arrchResult[45]; char arrchCode[12]; bool bOutLimit_Flag; int iMark; BYTE byteResultType; }; #pragma pack() //取消指定对齐,恢复缺省对齐

直接发送或接收

data.iNumber=1; strcpy(data.arrchResult,"hello"); strcpy(data.arrchCode,"0x29"); data.bOutLimit_Flag=true; data.iMark=200; data.byteResultType=23; //发送 udpSocket->writeDatagram((char *)&data,sizeof(data),QHostAddress::Broadcast,port); Test_data datagram; //接收 udpSocket->readDatagram((char*)&datagram,sizeof(datagram));

UDP发送和接收结构体消息(最原始的做法)

知道结构体的数据对齐的处理后,我们知道不能进行强转了,那么该怎么做呢?

我的做法是:将struct中的元素按字节大小一个个的存放到QByteArray中,QByteArray是连续的,接收时按大小再取出来就可以了。

直接上代码:

服务端(发送数据)

//udpserver.h #include #include #include #include #include #define BYTE unsigned char struct Test_data{ int iNumber; char arrchResult[45]; char arrchCode[12]; bool bOutLimit_Flag; int iMark; BYTE byteResultType; }; class UdpServer : public QWidget { Q_OBJECT public: UdpServer(QWidget *parent = 0); public slots: void StartBtnClicked(); void timeout(); private: QPushButton *startBtn; QVBoxLayout *mainLayout; int port; bool isStarted; QUdpSocket *udpSocket; QTimer *timer; QByteArray m_byteArray; }; #endif // UDPSERVER_H //udepserver.cpp #include "udpserver.h" #include #include UdpServer::UdpServer(QWidget *parent) : QWidget(parent) { //初始化 Test_data data; data.iNumber=1; strcpy(data.arrchResult,"hello"); strcpy(data.arrchCode,"0x29"); data.bOutLimit_Flag=true; data.iMark=200; data.byteResultType=23; qDebug()setText(tr("stop")); timer->start(1000); isStarted=true; } else { startBtn->setText(tr("start")); isStarted=false; timer->stop(); } } void UdpServer::timeout() { udpSocket->writeDatagram(byteArray.data(),byteArray.size(),QHostAddress::Broadcast,port); }

客户端接收数据

#ifndef UDPCLIENT_H #define UDPCLIENT_H #include #include #include #define BYTE unsigned char struct Test_data{ int iNumber; char arrchResult[45]; char arrchCode[12]; bool bOutLimit_Flag; int iMark; BYTE byteResultType; }; class UdpClient : public QWidget { Q_OBJECT public: UdpClient(QWidget *parent = 0); public slots: void dataReceived(); private: int port; QUdpSocket *udpSocket; }; #endif // UDPCLIENT_H

#include "udpclient.h" #include #include #include UdpClient::UdpClient(QWidget *parent) : QWidget(parent) { setWindowTitle(tr("UDP Client")); port=5555; udpSocket=new QUdpSocket(this); connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived())); bool result=udpSocket->bind(port); //绑定端口 if(!result) { QMessageBox::information(this,tr("error"),tr("udp socket create error")); return; } } void UdpClient::dataReceived() { while(udpSocket->hasPendingDatagrams()) //有未处理的报文 { Test_data* datagram=new Test_data; //用于存放接收的数据 QByteArray recvMsg; qDebug()pendingDatagramSize()); udpSocket->readDatagram(recvMsg.data(),recvMsg.size()); int pos=0; memcpy(&datagram->iNumber,recvMsg.constData(),sizeof(datagram->iNumber)); pos+=sizeof(datagram->iNumber); memcpy(datagram->arrchResult,recvMsg.constData()+pos,sizeof(datagram->arrchResult)); pos+=sizeof(datagram->arrchResult); memcpy(datagram->arrchCode,recvMsg.constData()+pos,sizeof(datagram->arrchCode)); pos+=sizeof(datagram->arrchCode); memcpy(&datagram->bOutLimit_Flag,recvMsg.constData()+pos,sizeof(datagram->bOutLimit_Flag)); pos+=sizeof(datagram->bOutLimit_Flag); memcpy(&datagram->iMark,recvMsg.constData()+pos,sizeof(datagram->iMark)); pos+=sizeof(datagram->iMark); memcpy(&datagram->byteResultType,recvMsg.constData()+pos,sizeof(datagram->byteResultType)); qDebug()


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有