uint16_t 在字符数组中

uint16_t in array of char

为了一个学校项目,我必须用 C 语言开发一个 TFTP 服务器。 我必须像这样在 char 数组中构建一个数据包:

 2 bytes    2 bytes    n bytes
+--------+-----------+--------+
|  CODE  |  Block #  |  Data  |
+--------+-----------+--------+

以下是我构建此数据包的方式:

int tftp_make_data(char *buffer, size_t *length, uint16_t block, const char *data, size_t n) {
    memset(buffer, 0, *length);
    *length = 0;
    *(buffer) = DATA;
    *length += sizeof(uint16_t);
    *(buffer + *length) = block;
    *length += sizeof(uint16_t);
    memcpy(buffer + *length, data, n);
    *length += n;

    return 0;
}

此函数用数据包内容填充buffer,并用数据包大小填充length。 如果 block 小于 128,这就可以正常工作。如果它比 128 更受欢迎,它就变成 -128。

你能帮帮我吗?

除非某物的大小是一个字节,否则不能将其分配给 *buffer。这两个分配都不正确:

*(buffer) = DATA;
*(buffer + *length) = block;

uint16_t时,使用memcpy:

uint16_t dataToWrite = ...;
memcpy(buffer + *length, &dataToWrite, sizeof(uint16_t));

您还没有完成,因为您需要决定分配什么 dataToWrite。如果你这样做

uint16_t dataToWrite = block;

通过线路发送的数据将按照硬件特定的顺序排列,这种情况永远不会发生。相反,您需要使用 hton-family functions 之一将您的号码转换为网络格式:

uint16_t dataToWrite = htons(block);

I check it on the same machine, just with

printf("block : %d\n", packet[sizeof(uint_16)]);

这是不正确的,原因与赋值相同:packet[sizeof(uint_16)] 从存储的 char/uint8_t 值生成 intunsigned int在位置 sizeof(uint_16),它也忽略另一个字节。

要解决此问题,您需要再次使用 memcpy。当然,如果你在书写端使用了htons,那么在打印之前需要使用ntohs

uint16_t dataToPrint;
memcpy(dataToPrint, &packet[sizeof(uint16_t)], sizeof(uint16_t));
dataToPrint = ntohs(dataToPrint);
printf("block : %u\n", dataToPrint);