文章网络部分使用QT
先看一个简单的发送整数的例子
这个例子直接引用于QT Creator快速入门这本书18-8样例源码,经过简单的修改,只是把发送字符串修改为了发送整数,方便查看字节数据
void Server::sendMessage()
{
// 用于暂存要发送的数据
QByteArray block;
QDataStreamout(&block, QIODevice::WriteOnly);
// 设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_5_6);
out << (quint16)0;
out << 5;
out.device()->seek(0);
out <<(quint16)(block.size() - sizeof(quint16));
// 获取已经建立的连接的套接字
QTcpSocket*clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection,&QTcpSocket::disconnected,clientConnection, &QTcpSocket::deleteLater);
clientConnection->write(block);
clientConnection->disconnectFromHost();
// 发送数据成功后,显示提示
ui->label->setText(tr("发送数据成功!!!"));
}
在这个例子中,我们打断点查看QByteArray字节数组的数据
可以看到QByteArray中的字节数据,首先是代表将要发送的实际数据的占位,之后是我们添加的整数,占4个字节
说到这里,正式进入如何发送结构体的部分,我们将结构体转换为字节数据,看代码,这段代码不再发送整数,而是发送结构体
void Server::sendMessage()
{
// 用于暂存要发送的数据
QByteArray block;
QDataStreamout(&block, QIODevice::WriteOnly);
using node = struct node
{
int a;
int b;
};
node temp;
temp.a=1;
temp.b=2;
// 设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_5_6);
out <<(quint16)0;
// out << 5;
char *tempData=newchar[sizeof(node)];
memcpy(tempData,&temp,sizeof(node));
block.append(tempData,sizeof(node));
out.device()->seek(0);
out <<(quint16)(block.size() - sizeof(quint16));
// 获取已经建立的连接的套接字
QTcpSocket*clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, &QTcpSocket::disconnected,clientConnection, &QTcpSocket::deleteLater);
clientConnection->write(block);
clientConnection->disconnectFromHost();
// 发送数据成功后,显示提示
ui->label->setText(tr("发送数据成功!!!"));
}
解释:
char *tempData=new char[sizeof(node)]; //建立结构体大小的字符数组
memcpy(tempData,&temp,sizeof(node)); //将结构体变量中的数据拷贝到字符数组中
lock.append(tempData,sizeof(node)); //将字符数组添加到QByteArray二进制数组中
现在再来看看QByteArray中的数据
一样的前两个是实际数据大小占位,后面的数据正好就是结构体中的数据
服务端完成,那么如果在客户端接收呢,首先上客户端代码
voidClient::readMessage()
{
QDataStream in(tcpSocket);
//设置数据流版本,这里要和服务器端相同
in.setVersion(QDataStream::Qt_5_6);
//如果是刚开始接收数据
if(blockSize==0){
//判断接收的数据是否大于两字节,也就是文件的大小信息所占的空间
//如果是则保存到blockSize变量中,否则直接返回,继续接收数据
if(tcpSocket->bytesAvailable()<(int)sizeof(quint16))return;
in>>blockSize;
}
//如果没有得到全部的数据,则返回,继续接收数据
if(tcpSocket->bytesAvailable()>message;
using node = struct node
{
int a;
int b;
};
uint len=sizeof(node);
char *temp=new char[len];
in.readRawData(temp,len);
node *mess=reinterpret_cast(temp);
// qDebug()<a<b;
//显示接收到的数据
ui->messageLabel->setText(QString::number(mess->a)+""+QString::number(mess->b));
// ui->messageLabel->setText(mess->a+""+mess->b);
}
首先建立和服务端一样的结构体,然后读取除占位的数据
in.readRawData(temp,len); //有关readBytes和readRawData的区别参考QT的官方文档,readBytes读出的数据会包含额外信息,而导致不是我们想要读取的仅仅结构体的数据
将结构体数据读取到temp字符数组之后,从二进制语义进行强制转换为结构体类型
node *mess=reinterpret_cast(temp);
这样就完成了结构体类型数据的发送。