2015-05-20 42 views
0

我是從我的Android手機整數發送與下面的代碼的字節(我只放了塊需要):字節爲int類型轉換網絡應用

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來實現:我收到數據包,但是我的整數結果(例如滾動)不正確。我使用從字節轉換爲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); 

閱讀其他討論我已經嘗試過的事情:卷=(INT *)(臨時);正如另一篇文章中的建議,但它不適用於我(別名編譯器錯誤)。任何想法來解決這個問題?感謝

+1

手機發送整數是4個字節我想這確實是在大端接受它時,你必須將它轉換成你的本地字節序.. 。void void getSubArray爲什麼不使用memcpy? –

+0

記得從網絡訂單轉換爲主機訂單。否則,你的字節*可能是錯誤的方式。 看看htonl和ntohl。 –

+0

是的,請打印'hex'中的值,並檢查字節是否不相反,如果你只是需要將它們從endiannes轉換爲正確的。 –

回答

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。現在假設接收系統具有簽名,二進制補碼char s,這並不少見。在這種情況下,在接收器上,這些字符將被解釋爲值0 0 1 -1(十進制)。現在有兩個問題:

  1. 施加移位運算符到負左操作數的行爲(即ch4在我的例子的值)是不確定的。
  2. -1 << 0的一個相當可能的實際行爲應該是產生-1(一個0位移位,評估其左操作數的值)。在這種情況下,整體計算值將爲256 + -1 = 255

當然,這只是一個例子,但是在16位32位int中只有一個清除了每個字節的高位。

通過使用適當的無符號數量執行計算可以解決這兩個問題。可以做這樣的:

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); 
+0

它的工作原理!謝謝 – Daniel

1
#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 

ALSE我已經修改了你的byteToInt功能的東西代替它更interessting