文章目录
- 前言
- 1. memcpy方式
- 1.1 发送整个结构体
- 1.2 发送部分数据
- 2. QDataStream
- 2.1 符号<<
- 2.2 wrieteRawData
- 总结
前言
做上位机的时候下发数据,数据是一个结构体,这里就阐述一下怎么通过TCP协议发送结构体。
我自己写的时候主要通过两种方式,一种是memcpy,另一种是用QDataStream。
先在mainwindow.h头文件中定义结构体:
struct EDWINWZY
{
char name='A';
int age=1;
}edwinwzy;
1. memcpy方式
1.1 发送整个结构体
函数原型为void *memcpy(void *destin, void *source, unsigned n);函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝n个字节到目标destin中
//定义bit流
QByteArray transfer;
//使用memcpy之前要分配内存空间
transfer.resize(sizeof(struct EDWINWZY));
//data.resize(sizeof(edwinwzy));//写法和上面一句效果一样
//内存拷贝
memcpy(transfer.data(),&edwinwzy,sizeof(edwinwzy));
//发送比特流数据
tcpSocket->write(transfer);
这种方式似乎就定死了只能发送结构体大小的数据,但其实不然,我可以通过QByteArray类的成员函数append来添加一个乃至多个字节的数据。
下面的append函数中备选的参数类型名就说明了很多,我可以添加单个字符,也可以添加n个同一个字符,也可以添加另外一个QByteArray的数据,即一串比特流数据,亦可以添加QString类型的数据。
1.2 发送部分数据
那这是在发送完一整个结构体之后再添加数据,如果我想单独一个一个发结构体的变量呢?
那其实直接用append就可以了。
//定义bit流
QByteArray transfer;
transfer.append(edwinwzy.name);
transfer.append(edwinwzy.age);
transfer.append('\n');
//发送比特流数据
tcpSocket->write(transfer);
有个要注意的是,有时候我最后不加换行符,接收端可能会出现无法显示的情况。这个我只在书中TCPClient项目中出现过,我用串口转网口来接收网口的数据,在串口端接收到的数据都是正常的。
2. QDataStream
这个就类似于C++ 的std::cout了。
不过发送的数据有两种情况。
2.1 符号<<
第一种情况是直接用<<
符号进行发送,这种发送会额外发送几个字节数据用来表示我发送的数据所占的字节数。
QByteArray tranferdata;
//后面这个QIODevice什么的也可以不选择添加。
QDataStream out(&tranferdata,QIODevice::WriteOnly|QIODevice::Append);
char A=a,B=b,C=c,D=d;
out<<A<<B<<C<<D;
tcpSocket->write(transfer);
实际上我们收到的字节数据用应该是 04 61 62 63 64,而我们其实只要后面的四个abcd的ascii码数据,那这个方法就有点问题了。
2.2 wrieteRawData
下面这个写原始数据的writeRawData
函数就解决了问题
如果我们要发送其他类型数据(不是char类型),那我们使用这个函数的时候最好做一个强制类型转换。
QByteArray tranferdata;
//后面这个QIODevice什么的也可以不选择添加。
QDataStream out(&tranferdata,QIODevice::WriteOnly|QIODevice::Append);
int A=91,B=92;
out.writeRawData((char*)&A,sizeof(A));
out.writeRawData((char*)&B,sizeof(B));
tcpSocket->write(transfer);
这种写法就解决了多发送字节的问题,只不过因为这里AB是以int举例,所以它们分别占4字节。
收到的数据就应该为 00 00 00 61 00 00 00 62
总结
这篇博客主要针对TCP发送结构体数据遇到的问题进行了归纳,发单个以及发部分情况都可以实现。