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

UDP receive data as unsigned char

本文关键字:数据 无符号 字符 UDP      更新时间:2023-10-16

我正在尝试使用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值,如果char的顶部位为1(即为负数),则会导致ff按比例分配到顶部字节。您应该首先将其强制转换为无符号类型,然后扩展为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;
}

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

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

  • 另一种可能性是简单地执行按位And:(recvline[i] & 0xff)。由于自动整体升级,这甚至不需要演员阵容。


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