C++:memcpy与大小端变换

背景:

在使用socket通信接收数据的时候,发现了数据异常

#include <iostream>
#include <string>
#include <winsock2.h>

using namespace std;

//定义消息长度
#define MAX_MSG_SIZE 1024
#pragma comment(lib,"ws2_32.lib")

template <typename T>
T Little2Big_int(T a)
{
    T b = 0;
    *(char*)(&b) = *((char*)(&a) + 3);
    *((char*)(&b)+1) = *((char*)(&a) + 2);
    *((char*)(&b) + 2) = *((char*)(&a) + 1);
    *((char*)(&b) + 3) = *((char*)(&a) + 0);
    return b;
}

//初始化套接字库
void initWsaData() {
    WSADATA wsaData;
    WORD vCode = MAKEWORD(2, 2);
    int err = WSAStartup(vCode, &wsaData);
    if (err == -1) {
        cout << "初始化套接字库失败" << endl;
        exit(-1);
    }
    else {
        cout << "初始化套接库成功" << endl;
    }
    //检查套接字库版本号
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wHighVersion) != 2) {
        cout << "套接字库版本号不符" << endl;
        exit(-1);
    }
    else {
        cout << "套接字库版本检验通过" << endl;
    }
}


void mainTcp() {
    initWsaData();
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == SOCKET_ERROR) {
        cout << "创建套接字失败" << endl;
        exit(-1);
    }
    else {
        cout << "创建套接字成功" << endl;
    }
    //设置地址
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(9999);
    sin.sin_addr.s_addr = inet_addr("10.10.0.144");
    
    //连接服务器
    int connStatus = connect(sock, (struct sockaddr*)&sin, sizeof(sin));
    if (connStatus == -1) {
        cout << "连接服务器失败" << endl;
        exit(-1);
    }
    //发送与接收数据
    while (true) {
        cout << "发送请求" << endl;
        char sendBuf[9] = { 0xe9, 0, 0x0b, 0, 0, 0, 0, 0x0d, 0x0a };
        int sendStatus = send(sock, sendBuf, sizeof(sendBuf), 0);
        if (sendStatus == 0) {
            cout << "发送信息失败" << endl;
            break;
        }
        Sleep(1000);
        char recvBuf[MAX_MSG_SIZE];
        memset(recvBuf, 0, MAX_MSG_SIZE);
        int recvStatus = recv(sock, recvBuf, MAX_MSG_SIZE, 0);
        if (recvStatus == -1) {
            cout << "接收消息失败" << endl;
            break;
        }
        else {
            //cout << "服务端信息:" << recvBuf << endl;
        }
        int data_len;
        memcpy(&data_len, &recvBuf[3], 4);
        data_len = Little2Big_int(data_len);

        unsigned int points_16[16][2];
        int offset_stream = 7;
        for (int i = 0; i < 16; i++)
        {
            memcpy(&points_16[i][0], &recvBuf[offset_stream + i * 4], 4);
            points_16[i][0] = Little2Big_int(points_16[i][0]);
            memcpy(&points_16[i][1], &recvBuf[offset_stream +64 + i * 4], 4);
            points_16[i][1] = Little2Big_int(points_16[i][1]);
        }

        for (int i = 0; i < 16; i++)
        {
            cout << points_16[i][0] << "\t";
        }
        cout << endl;

        for (int i = 0; i < 16; i++)
        {
            cout << points_16[i][1] << "\t";
        }
        cout << endl;
        int i = 0;
    }
    //关闭套接字及套接字库
    closesocket(sock);
    WSACleanup();
}

int data_len;
memcpy(&data_len, &recvBuf[3], 4);

在这里,我已知接收到数据前三个字节是标志,从第四个字节开始的一个int代表数据长度,但是当memcpy将数据拷贝过去后发现数据和预期不一致,查看内存数据原来是大小端导致的,

大端:将高位存放在低地址,小端:将高位存放在高地址

上图可以看出我的VS是小端,但是socket接收到的数据是大端,因此出错。

可以通过简单的函数实现对四字节数据的大小端转换(因为我这里需要用到的是四字节的int和无符号int)

template <typename T>
T Little2Big_int(T a)
{
    T b = 0;
    *(char*)(&b) = *((char*)(&a) + 3);
    *((char*)(&b)+1) = *((char*)(&a) + 2);
    *((char*)(&b) + 2) = *((char*)(&a) + 1);
    *((char*)(&b) + 3) = *((char*)(&a) + 0);
    return b;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值