在我的代码中使用 htons() 会将所有零放入缓冲区,我不明白为什么
Using htons() in my code puts all zeros in the buffer and I don't understand why
我需要在我的代码中使用 htons()
将小端顺序短字节顺序转换为网络(大端)字节顺序。我有这个代码:
int PacketInHandshake::serialize(SOCKET connectSocket, BYTE* outBuffer, ULONG outBufferLength) {
memset(outBuffer, 0, outBufferLength);
const int sizeOfShort = sizeof(u_short);
u_short userNameLength = (u_short)strlen(userName);
u_short osVersionLength = (u_short)strlen(osVersion);
int dataLength = 1 + (sizeOfShort * 2) + userNameLength + osVersionLength;
outBuffer[0] = id;
outBuffer[1] = htons(userNameLength);// htons() here
printf("u_short byte 1: %c%c%c%c%c%c%c%c\n", BYTE_TO_BINARY(outBuffer[1]));
printf("u_short byte 2: %c%c%c%c%c%c%c%c\n", BYTE_TO_BINARY(outBuffer[2]));
for (int i = 0; i < userNameLength; i++) {
outBuffer[1 + sizeOfShort + i] = userName[i];
}
outBuffer[1 + sizeOfShort + userNameLength] = htons(osVersionLength);// and here
for (int i = 0; i < osVersionLength; i++) {
outBuffer[1 + (sizeOfShort * 2) + userNameLength + i] = osVersion[i];
}
int result;
result = send(connectSocket, (char*)outBuffer, dataLength, 0);
if (result == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
}
printf("PacketInHandshake sent: %ld bytes\n", result);
return result;
}
这导致发送这样的数据包:
如您所见,使用htons()
的长度指示字节全部为零,它们应该分别为00 07
和00 16
。
这是控制台输出:
u_short byte 1: 00000000
u_short byte 2: 00000000
PacketInHandshake sent: 34 bytes
如果我删除 htons()
并按原样将 u_shorts 放入缓冲区,一切都按预期进行,小端排序:
u_short byte 1: 00000111
u_short byte 2: 00000000
PacketInHandshake sent: 34 bytes
那我做错了什么?
转换 16 位数字的字节顺序并将其存储在字节数组中是微不足道的,不需要库函数。假设 32 位 CPU:
uint16_t u16 = ...;
uint8_t out[2];
out[0] = ((uint32_t)u16 >> 8) & 0xFFu;
out[1] = ((uint32_t)u16 >> 0) & 0xFFu;
转换和 u
后缀是阻止隐式提升到 int
的好习惯,这在某些情况下是有问题的,因为它是一个有符号数。
由于转换不关心底层的字节序,上面的代码适用于 big-to-little 和 little-to-big 转换,只要你从一个转换到另一个。
这扩展到 32 位类型为:
uint32_t u32 = ...;
uint8_t out[4];
out [0] = ((uint32_t)u32 >> 24) & 0xFFu;
out [1] = ((uint32_t)u32 >> 16) & 0xFFu;
out [2] = ((uint32_t)u32 >> 8) & 0xFFu;
out [3] = ((uint32_t)u32 >> 0) & 0xFFu;
我需要在我的代码中使用 htons()
将小端顺序短字节顺序转换为网络(大端)字节顺序。我有这个代码:
int PacketInHandshake::serialize(SOCKET connectSocket, BYTE* outBuffer, ULONG outBufferLength) {
memset(outBuffer, 0, outBufferLength);
const int sizeOfShort = sizeof(u_short);
u_short userNameLength = (u_short)strlen(userName);
u_short osVersionLength = (u_short)strlen(osVersion);
int dataLength = 1 + (sizeOfShort * 2) + userNameLength + osVersionLength;
outBuffer[0] = id;
outBuffer[1] = htons(userNameLength);// htons() here
printf("u_short byte 1: %c%c%c%c%c%c%c%c\n", BYTE_TO_BINARY(outBuffer[1]));
printf("u_short byte 2: %c%c%c%c%c%c%c%c\n", BYTE_TO_BINARY(outBuffer[2]));
for (int i = 0; i < userNameLength; i++) {
outBuffer[1 + sizeOfShort + i] = userName[i];
}
outBuffer[1 + sizeOfShort + userNameLength] = htons(osVersionLength);// and here
for (int i = 0; i < osVersionLength; i++) {
outBuffer[1 + (sizeOfShort * 2) + userNameLength + i] = osVersion[i];
}
int result;
result = send(connectSocket, (char*)outBuffer, dataLength, 0);
if (result == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
}
printf("PacketInHandshake sent: %ld bytes\n", result);
return result;
}
这导致发送这样的数据包:
如您所见,使用htons()
的长度指示字节全部为零,它们应该分别为00 07
和00 16
。
这是控制台输出:
u_short byte 1: 00000000
u_short byte 2: 00000000
PacketInHandshake sent: 34 bytes
如果我删除 htons()
并按原样将 u_shorts 放入缓冲区,一切都按预期进行,小端排序:
u_short byte 1: 00000111
u_short byte 2: 00000000
PacketInHandshake sent: 34 bytes
那我做错了什么?
转换 16 位数字的字节顺序并将其存储在字节数组中是微不足道的,不需要库函数。假设 32 位 CPU:
uint16_t u16 = ...;
uint8_t out[2];
out[0] = ((uint32_t)u16 >> 8) & 0xFFu;
out[1] = ((uint32_t)u16 >> 0) & 0xFFu;
转换和 u
后缀是阻止隐式提升到 int
的好习惯,这在某些情况下是有问题的,因为它是一个有符号数。
由于转换不关心底层的字节序,上面的代码适用于 big-to-little 和 little-to-big 转换,只要你从一个转换到另一个。
这扩展到 32 位类型为:
uint32_t u32 = ...;
uint8_t out[4];
out [0] = ((uint32_t)u32 >> 24) & 0xFFu;
out [1] = ((uint32_t)u32 >> 16) & 0xFFu;
out [2] = ((uint32_t)u32 >> 8) & 0xFFu;
out [3] = ((uint32_t)u32 >> 0) & 0xFFu;