UDP 以无符号字符形式接收数据

UDP receive data as unsigned char

我正在尝试使用 UDP 从网络接收一些数据并对其进行解析。

这是代码,

char recvline[1024];
int n=recvfrom(sockfd,recvline,1024,0,NULL,NULL);

for(int i=0;i<n;i++)
   cout << hex <<static_cast<short int>(recvline[i])<<" ";

打印输出,

19 ffb0 0 0 ff88 d 38 19 48 38 0 0 2 1 3 1 ff8f ff82 5 40 20 16 6 6 22 36 6 2c 0 0 0 0 0 0 0 0

但我期待这样的输出,

19 b0 0 0 88 d 38 19 48 38 0 0 2 1 3 1 8f 82 5 40 20 16 6 6 22 36 6 2c 0 0 0 0 0 0 0 0

ff 不应出现在打印输出中。

实际上我必须根据每个字符来解析这个数据,

喜欢,

parseCommand(recvline);

解析代码看起来,

void parseCommand( char *msg){

  int commId=*(msg+1);

  switch(commId){
    case 0xb0 : //do some operation
                break;

    case 0x20 : //do another operation
                break;
   }
}

在调试时我得到了 commId=-80 关注。

注: 在 Linux 中,我通过代码成功输出,请注意,我使用 unsigned char 而不是 char 作为读取缓冲区。

unsigned char recvline[1024];
int n=recvfrom(sockfd,recvline,1024,0,NULL,NULL); 

其中 Windows recvfrom() 不允许第二个参数作为 unsigned 它给出构建错误,所以我选择 char

看起来您可能获得了正确的值,但是在打印符号期间您转换为 short int 会扩展您的 char 值,如果最高位,则导致 ff 传播到最高字节你的 char 是 1(即它是负数)。您应该先将其转换为无符号类型,然后扩展为 int,因此您需要 2 次转换:

cout << hex << static_cast<short int>(static_cast<uint8_t>(recvline[i]))<<" ";

我已经对此进行了测试,它的行为符合预期。

回复你的分机:读到的数据没问题,就看你怎么解读了。要正确解析你应该:

  uint8_t commId= static_cast<uint8_t>(*(msg+1));

  switch(commId){
    case 0xb0 : //do some operation
                break;

    case 0x20 : //do another operation
                break;
   }

当您将数据存储在有符号数据类型中时 conversions/promotion 到更大的数据类型将首先对值进行符号扩展(用 MSB 的值填充高位),即使它随后被转换为无符号数据类型。

  • 一个解决方案是首先将 recvline 定义为 uint8_t[],然后在将其传递给 recvfrom 函数时将其转换为 char* .这样,您只需要转换一次,并且在 windows 和 linux 版本中使用相同的代码。另外 uint8_t[] (至少对我而言)清楚地表明您正在使用数组作为原始内存而不是某种字符串。

  • 另一种可能性是简单地执行按位与:(recvline[i] & 0xff)。由于自动积分提升,这甚至不需要转换。


个人笔记:
C 和 C++ 标准还没有为原始内存提供单独的类型,这真的很烦人,但运气好的话我们会在未来的标准修订版中获得 byte 类型。