【问题标题】:byte to int type conversion network applicationbyte 到 int 类型转换网络应用
【发布时间】:2015-05-20 20:23:34
【问题描述】:

我使用以下代码从我的 android 手机整数作为字节发送(我只放置了所需的块):

private byte[] intToByteArray ( final int i ) throws IOException {      
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}
//thread sender
        data = new byte[16];
        ...
        try {
            temp = intToByteArray((int) (roll*100));
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        data[3] = temp[0];
        data[4] = temp[1];
        data[5] = temp[2];
        data[6] = temp[3];
        ...
        p = new DatagramPacket(data, 16);
        udpSocket.send(p);

发送代码有效,因为我已经用收到的 Java 进行了尝试,结果是正确的。真正的接收器必须使用嵌入式设备 Murata SN8200 实现:我收到了数据包,但我的整数结果(例如,滚动)不正确。我用于从 byte 转换为 int 的代码如下:

void getSubArray(char* dest, char* source, int start, int end){
   uint8_t i, j = 0;
   for(i=start; i<end; i++){
       dest[j] = source[i];
       j++;
   }
}
int byteToInt(char* bytes)
{
  int ch1 = bytes[0];
  int ch2 = bytes[1];
  int ch3 = bytes[2];
  int ch4 = bytes[3];
  if ((ch1 | ch2 | ch3 | ch4) < 0)
      WPRINT_APP_INFO ( ("boh\r\n"));
  return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
...
//thread receiver
wiced_packet_get_data(packet, 0, (uint8_t**)&rx_data, &rx_data_length, &available_data_length);
traffic_type = rx_data[0];
        id = rx_data[1];
        takeOffPressed = rx_data[2];
        getSubArray(temp, rx_data, 3, 7);
        roll = byteToInt(temp);
        WPRINT_APP_INFO ( ("Rx: \" Packet Type: %c Id: %c  TakeOffPressed = %c \r\n  roll: %d \r\n ", (unsigned char )traffic_type, (unsigned char )id, (unsigned char)takeOffPressed, roll);

阅读我已经尝试过的其他讨论:roll = (int*)(temp);正如另一篇文章中所建议的那样,但它对我不起作用(别名编译器错误)。有什么想法可以解决这个问题吗?谢谢

【问题讨论】:

  • 您的手机发送 4 个字节的整数,我想它是以大字节序进行的?接收时您必须将其转换为本地字节序...代替 void getSubArray 为什么不使用 memcpy ?
  • 记得从网络订单转换为主机订单。否则你的字节可能是错误的。看看 htonl 和 ntohl。
  • 是的,请打印hex 中的值并检查字节是否不倒序,如果您只需将它们从它们的字节序转换为正确的字节序。
  • 我看不出您提供的 Java 代码如何“工作”,因为 p = new DatagramPacket(data, 16); udpSocket.send(p[0]); 甚至不应该编译
  • @JesperBangsholt,是的,不是的。网络字节顺序不会自动发生——消息的字节顺序由发送者选择。在这种情况下,它碰巧是网络字节顺序,但这是DataOutputStream,writeInt()的行为的函数,其文档没有按照这些术语进行转换。

标签: java c casting network-programming type-conversion


【解决方案1】:

您有一些可能的符号混淆。考虑你的byteToInt() 函数:

int byteToInt(char* bytes)
{
  int ch1 = bytes[0];
  int ch2 = bytes[1];
  int ch3 = bytes[2];
  int ch4 = bytes[3];
  if ((ch1 | ch2 | ch3 | ch4) < 0)
      WPRINT_APP_INFO ( ("boh\r\n"));
  return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

假设发送的 4 字节值是 511(十进制)。然后发送的字节为0x00 0x00 0x01 0xff。现在假设接收系统特征有符号,二进制补码chars,这种情况并不少见。在这种情况下,在接收器上,这些字符将被解释为值0 0 1 -1(十进制)。现在有两个问题:

  1. 将移位运算符应用于负左操作数(即我的示例中的 ch4 的值)的行为未定义。
  2. -1 &lt;&lt; 0 的一个合理可能的实际行为是产生-1(计算其左操作数值的零位移)。在这种情况下,总计算值将是256 + -1 = 255

当然,这只是一个例子,但只有十六分之一的 32 位 ints 将每个字节的高位清除。

这两个问题都可以通过使用适当的无符号量执行计算来解决。可以这样做:

int byteToInt(char* bytes)
{
  uint8_t ch1 = bytes[0];
  uint8_t ch2 = bytes[1];
  uint8_t ch3 = bytes[2];
  uint8_t ch4 = bytes[3];
  return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

还要注意,提取子数组以传递给byteToInt() 是一种浪费。最好只使用一点指针算法:

roll = byteToInt(rx_data + 3);

【讨论】:

    【解决方案2】:
    #include <sdint.h>
    #include <string.h>
    #include <netinet/in.h>
    
    uint32_t byteToInt(char* bytes)
    {
     uint8_t b[4];
     memcpy(b, bytes, 4);
     if ((b[0] | b[1] | b[2] | b[3]) < 0)WPRINT_APP_INFO ( ("boh\r\n"));
     return ntohl(*((uint32_t *)b));
    }
     ...
     //thread receiver
    wiced_packet_get_data(packet, 0, (uint8_t**)&rx_data, &rx_data_length, &available_data_length);
    traffic_type = rx_data[0];
    id = rx_data[1];
    takeOffPressed = rx_data[2];
    memcpy(temp, rx_data+3, 4);
    roll = byteToInt(temp);
    WPRINT_APP_INFO ( ("Rx: \" Packet Type: %c Id: %c  TakeOffPressed = %c \r\n  roll: %d \r\n ", (unsigned char )traffic_type, (unsigned char )id, (unsigned char)takeOffPressed, roll);
    

    不需要

    void getSubArray(char* dest, char* source, int start, int end)
    

    你可以用一个替换它

    memcpy(void* dest, void* src, size_t t);//from string.h
    

    另外我已经将你的 byteToInt 函数修改为更有趣的东西

    【讨论】:

      猜你喜欢
      • 2014-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      相关资源
      最近更新 更多