背景:
在使用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;
}