【问题标题】:Unpacking integer from byte array从字节数组中解包整数
【发布时间】:2019-01-08 19:29:08
【问题描述】:

如果这很明显,请原谅我,但我正在使用字节数组通过网络发送数据,我需要将一个整数塞入其中,然后将其从另一端取出。

示例中的类型定义:

uint8_t *dest;
uint8_t *ciphertext;
size_t  cbytes; // length of ciphertext
uint8_t iv[16];
uint8_t tag[16];

作者的相关部分:

size_t bytes = 0;
memcpy(&dest[bytes], iv, sizeof(iv));
bytes = sizeof(iv);
memcpy(&dest[bytes], (void*)htonl(cbytes), sizeof(uint32_t));
bytes += sizeof(uint32_t);
memcpy(&dest[bytes], ciphertext, cbytes);
bytes += cbytes;
memcpy(&dest[bytes], tag, sizeof(tag));
bytes += sizeof(tag);

这是将cbytes 作为整数填充到字节数组中的正确方法吗?如果没有,有什么更好的方法?

现在,使用这个字节数组,我如何将cbytes 读回一个整数(或 size_t)?其余的可以直接复制回来,但不确定如何处理整数。

【问题讨论】:

标签: c network-programming endianness


【解决方案1】:

你问的是这段代码:

memcpy(&dest[bytes], (void*)htonl(cbytes), sizeof(uint32_t));

不,这根本不正确。您正在将 htonl 的返回值转换为指针。然而,它不是一个有效的指针。您必须拥有一个 uint32_t 类型的对象用于发送:

uint32_t cbytes32 = htonl(cbytes);
memcpy(&dest[bytes], &cbytes32, sizeof(uint32_t));

在现代 C 中也可以在一行上执行此操作,使用 复合文字 创建一个包含一个 uint32_t 内联的数组:

memcpy(&dest[bytes], (uint32_t[]){ htonl(cbytes) }, sizeof(uint32_t));

但语法确实看起来没有更好。

要读入它,你需要将它读入一个uint32_t类型的对象,然后是ntohl它,返回值你可以存储到size_t中:

uint32_t size32;
size_t size;
memcpy(&size32, src, sizeof size32)
size = ntohl(size32);

然后,我会格外小心,您可能在其他地方使用 64 位 size_t,但在此处将其截断为 32 位。可能没问题,但这需要记录在案。 64位应该对每个人都够用了,可惜没有htonll函数。


最后,你可以写dest + bytes 而不是&dest[bytes] 以减少按键次数。甚至更少,您可以制作另一个指针:

uint8_t *cur = dest;
memcpy(cur, iv, sizeof iv);
cur += sizeof iv;
uint32_t cbytes32 = htonl(cbytes);
memcpy(cur, &cbytes32, sizeof cbytes32);
cur += sizeof cbytes32;
memcpy(cur, ciphertext, cbytes32);
cur += cbytes32;
memcpy(cur, tag, sizeof tag);
cur += sizeof tag;
size_t nbytes = cur - dest;

请注意,如果您使用的是 流式套接字 (TCP),通常不需要将它们复制到中间缓冲区 - 只需使用单独的 read 调用发送 4、8 个字节- 或者至少,在 size 调用之后不要费心将 long 数组复制到同一个缓冲区中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 2010-10-07
    相关资源
    最近更新 更多