【问题标题】:How to extract values of different sizes from an array of uint8_t?如何从 uint8_t 数组中提取不同大小的值?
【发布时间】:2017-03-12 23:32:15
【问题描述】:

我正在尝试接收 TCP 套接字的消息并将其存储在 uint8_t 数组中。 我要接收的缓冲区长度为 8 个字节,包含 4 个唯一值。 字节 1:值 1,即 uint8_t,字节 2-3:值 2,即 uint16_t,字节 4:值 3,即 uint8_t,字节 5-8:值 4,即无符号长整数。 Endianness 是大端顺序。

int numBytes = 0;
uint8_t buff [8];
if ((numBytes = recv(sockfd, buff, 8, 0)) == -1)
{
    perror("recv");
    exit(1);
}

uint8_t *pt = buff;
printf("buff[0] = %u\n", *pt);
++pt;
printf("buff[1] = %u\n", *(uint16_t*)pt);

但是第二个printf 打印出一个意外的值。我是否做了错误的事情来提取这两个字节,或者我的打印功能有问题?

【问题讨论】:

  • 在您解释“字节 2-3:值 2”的含义之前无法回答,即这些字节应如何转换为值。值 4 相同。
  • 我们不知道多字节值的字节顺序,但我认为通过使用指针而不是直接将 buff 索引为数组来使问题复杂化没有任何目的,并逐个元素提取值。
  • @PeteBecker 对我来说似乎很清楚:值 2 表示第二个值。
  • @WeatherVane - 嗯?当然 value2 表示第二个值。您在回复之前阅读我的评论吗?
  • 关于 TCP 的重要说明:它是基于流的,而不是基于消息的。永远不要仅仅因为recv 没有返回错误就认为您收到了整个消息。 recv 返回它可用的内容最多您要求的字节数。在这种情况下,recv 可以返回 0(礼貌地关闭套接字)、1 或 2。如果您需要 N 个字节,则可能必须循环 recv,直到收到 N 个字节。

标签: c++ c arrays pointers tcp


【解决方案1】:

大概是这样(大端)

uint8_t buff [8];
// ... 
uint8_t       val1 = buff[0];
unit16_t      val2 = buff[1] * 256 + buff[2];
unit8_t       val3 = buff[3];
unsigned long val4 = buff[4] * 16777216 + buff[5] * 65536 + buff[6] * 256 + buff[7];

【讨论】:

    【解决方案2】:

    数据到达缓冲区后,您需要处理 2 个问题。

    首先是遵守别名规则,这是通过仅将非字符类型指针转换为char* 来实现的,因为char 可以别名任何东西。您应该从不char* 转换为非字符类型指针。

    第二个是遵循网络字节排序协议,通过网络传输的整数在传输前转换为网络顺序,接收后从网络顺序转换。为此,我们通常使用htonshtonlntohsntohl

    类似这样的:

    // declare receive buffer to be char, not uint8_t
    char buff[8]; 
    
    // receive chars in buff here ...
    
    // now transfer and convert data
    uint8_t a;
    uint16_t b;
    uint8_t c;
    uint32_t d;
    
    a = static_cast<uint8_t>(buff[0]);
    
    // always cast the receiving type* to char*
    // never cast char* to receiving type*
    std::copy(buff + 1, buff + 3, (char*)&b)
    
    // convert from network byte order to host order
    b = ntohs(b); // short version (uint16_t)
    
    c = static_cast<uint8_t>(buff[3]);
    
    std::copy(buff + 4, buff + 8, (char*)&d)
    
    d = ntohl(d); // long version (uint32_t)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多