繁体   English   中英

在我的代码中使用 htons() 将所有零放在缓冲区中,我不明白为什么

[英]Using htons() in my code puts all zeros in the buffer and I don't understand why

我需要在我的代码中使用htons()将 little-endian 排序的 short 转换为网络(big-endian)字节顺序。 我有这个代码:

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 0700 16

这是控制台 output:

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的好习惯,这在某些情况下是有问题的,因为它是一个有符号数。

由于班次不关心潜在的字节序,只要您从一个到另一个 go,上述代码适用于大到小和小到大的转换。

这可以扩展到 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转换整数。 我以前就是这样做的。

    *(int16_t *)(&outBuffer[1]) = htons(userNameLength);

现在我写(强制转换抑制编译器警告):

    outbuffer[1] = (char)(userNameLength >> 8);
    outbuffer[2] = (char)userNameLength;

无论哪种方式都有效。 我现在使用第二个,因为没有htonq

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM