我试图使用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
答案 0 :(得分:3)
看起来您可能获得了正确的值,但是在打印期间您向short int
转换符号扩展了您的字符值,导致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;
}
答案 1 :(得分:3)
当您将数据存储在有符号数据类型中时,转换/提升为更大的数据类型将首先签署扩展值(使用MSB的值填充高位),即使它随后转换为无符号数据类型。
一种解决方案是将recvline
定义为uint8_t[]
,并将char*
传递给recvfrom
时将其转换为uint8_t[]
。这样,你只需要抛出一次,你在windows和linux版本中使用相同的代码。另外(recvline[i] & 0xff)
(至少对我来说)清楚地表明你正在使用数组作为原始内存而不是某种字符串。
另一种可能性是简单地执行按位和:Control source
。由于自动积分推广,这甚至不需要演员。
个人注意事项:
真的很烦人的是,C和C ++标准没有为原始内存提供单独的类型(但是),但幸运的是,在未来的标准版本中可以获得byte
类型。