利用Qt實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)報(bào)文大小端數(shù)據(jù)的收發(fā)
1.大小端數(shù)據(jù)簡(jiǎn)介
大小端(Endianness)是計(jì)算機(jī)體系結(jié)構(gòu)的一個(gè)術(shù)語,它描述了多字節(jié)數(shù)據(jù)在內(nèi)存中的存儲(chǔ)順序。以下是大小端的定義和它們的特點(diǎn):
大端(Big-Endian)
在大端模式中,一個(gè)字的最高有效字節(jié)(MSB,即最左邊的那位)存儲(chǔ)在最低的內(nèi)存地址處,而最低有效字節(jié)(LSB,即最右邊的那位)存儲(chǔ)在最高的內(nèi)存地址處。
例如,假設(shè)有一個(gè)16位的數(shù)字 0x1234,其在內(nèi)存中的存儲(chǔ)順序如下:
地址增加方向 -->
[ 12 ] [ 34 ]
其中 [12] 是高字節(jié),存儲(chǔ)在低地址處;[34] 是低字節(jié),存儲(chǔ)在高地址處。
小端(Little-Endian)
在小端模式中,情況正好相反:一個(gè)字的最低有效字節(jié)存儲(chǔ)在最低的內(nèi)存地址處,而最高有效字節(jié)存儲(chǔ)在最高的內(nèi)存地址處。
繼續(xù)上面的例子,16位的數(shù)字 0x1234 在小端模式下的存儲(chǔ)順序如下:
地址增加方向 -->
[ 34 ] [ 12 ]
其中 [34] 是低字節(jié),存儲(chǔ)在低地址處;[12] 是高字節(jié),存儲(chǔ)在高地址處。
2.小端數(shù)據(jù)收發(fā)
假設(shè)我們現(xiàn)在有一個(gè)UDP頭的數(shù)據(jù)結(jié)構(gòu)如下所示。
//UDP協(xié)議頭
typedef struct
{
quint16 type; //報(bào)文類型
quint16 num; //報(bào)文序號(hào),取值范圍為0~65535
quint32 len; //報(bào)文長(zhǎng)度
quint16 srcAddr; //信源地址
quint16 dstAddr; //信宿地址
quint8 year; //發(fā)送時(shí)間 年份后兩位 UTC時(shí)間
quint8 month;
quint8 day;
quint8 hour;
quint8 minute;
quint8 second;
}UdpHeader;
數(shù)據(jù)發(fā)送:組包。
QByteArray pack(const Protocol::UdpHeader &header)
{
QByteArray byte;
byte.append((char*)&(header.type),2);
byte.append((char*)&(header.num),2);
byte.append((char*)&(header.len),4);
byte.append((char*)&(header.srcAddr),2);
byte.append((char*)&(header.dstAddr),2);
QString format = "yy-MM-dd-hh-mm-ss";
QDateTime dateTime = QDateTime::currentDateTime();
dateTime.setTimeSpec(Qt::LocalTime);
QDateTime utcTime = dateTime.toUTC();
QString strUtcTime = utcTime.toString(format);
QStringList timeList = strUtcTime.split('-');
quint8 year = timeList.at(0).toInt();
quint8 month = timeList.at(1).toInt();
quint8 day = timeList.at(2).toInt();
quint8 hour = timeList.at(3).toInt();
quint8 minute = timeList.at(4).toInt();
quint8 sec = timeList.at(5).toInt();
byte.append(year);
byte.append(month);
byte.append(day);
byte.append(hour);
byte.append(minute);
byte.append(sec);
return byte;
}
數(shù)據(jù)接收:拆包
void unPack(const QByteArray &byte, Protocol::UdpHeader &header)
{
if(byte.size() != UDP_HEADER_LEN)
{
return;
}
memcpy(&header,byte.data(),sizeof(Protocol::UdpHeader));
}
3.大端數(shù)據(jù)收發(fā)
還是上面的頭例子。
數(shù)據(jù)發(fā)送:組包
使用QDataStream類作為輔助,設(shè)置setByteOrder為大端序列。
QByteArray packBigEndian(const Protocol::UdpHeader &header)
{
QByteArray byte;
QDataStream stream(&byte,QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::BigEndian);
stream<<(header.type);
stream<<(header.num);
stream<<(header.len);
stream<<(header.srcAddr);
stream<<(header.dstAddr);
QString format = "yy-MM-dd-hh-mm-ss";
QDateTime dateTime = QDateTime::currentDateTime();
dateTime.setTimeSpec(Qt::LocalTime);
QDateTime utcTime = dateTime.toUTC();
QString strUtcTime = utcTime.toString(format);
QStringList timeList = strUtcTime.split('-');
quint8 year = timeList.at(0).toInt();
quint8 month = timeList.at(1).toInt();
quint8 day = timeList.at(2).toInt();
quint8 hour = timeList.at(3).toInt();
quint8 minute = timeList.at(4).toInt();
quint8 sec = timeList.at(5).toInt();
stream<<year;
stream<<month;
stream<<day;
stream<<hour;
stream<<minute;
stream<<sec;
return byte;
}
數(shù)據(jù)接收:拆包
對(duì)于多字節(jié)的數(shù)據(jù),都需要單獨(dú)使用qToBigEndian轉(zhuǎn)換為大端。
void unPackBigEndian(const QByteArray &byte, Protocol::UdpHeader &header)
{
if(byte.size() != UDP_HEADER_LEN)
{
return;
}
memcpy(&header,byte.data(),sizeof(Protocol::UdpHeader));
header.type = qToBigEndian(header.type);
header.num= qToBigEndian(header.num);
header.len= qToBigEndian(header.len);
header.srcAddr= qToBigEndian(header.srcAddr);
header.dstAddr= qToBigEndian(header.dstAddr);
}
到此這篇關(guān)于利用Qt實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)報(bào)文大小端數(shù)據(jù)的收發(fā)的文章就介紹到這了,更多相關(guān)Qt大小端數(shù)據(jù)收發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c語言常量定義規(guī)則知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是關(guān)于c語言常量定義規(guī)則知識(shí)點(diǎn)總結(jié),需要的朋友們可以學(xué)習(xí)下。2020-03-03
Qt重寫QComboBox實(shí)現(xiàn)下拉展示多列數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Qt如何重寫QComboBox實(shí)現(xiàn)下拉展示多列數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11
OpenGL實(shí)現(xiàn)不規(guī)則區(qū)域填充算法
這篇文章主要為大家詳細(xì)介紹了OpenGL實(shí)現(xiàn)不規(guī)則區(qū)域填充算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
C++設(shè)計(jì)模式編程中Facade外觀模式的使用實(shí)例解析
這篇文章主要介紹了C++設(shè)計(jì)模式編程中Facade外觀模式的使用實(shí)例解析,外觀模式的主要用途就是為子系統(tǒng)的復(fù)雜處理過程提供方便的調(diào)用方法,需要的朋友可以參考下2016-03-03

