C++ QT通过网络发送结构体

文章网络部分使用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字节数组的数据

C++ QT通过网络发送结构体_第1张图片

可以看到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中的数据

C++ QT通过网络发送结构体_第2张图片

一样的前两个是实际数据大小占位,后面的数据正好就是结构体中的数据

服务端完成,那么如果在客户端接收呢,首先上客户端代码

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);

这样就完成了结构体类型数据的发送。


你可能感兴趣的:(c++)