2010-04-20 67 views
4

我與服務器進行通信時,發送到服務器的每個消息具有與所述消息的長度進行填充,爪哇實施htonl

unsigned int len = htonl(msg.size()); 

在C運行長度通過htonl和填充該消息有效,在Java AFAIK字節順序已經在網絡順序,所以我假設我所要做的就是在消息傳遞到流之前寫入字符串長度,但這不起作用,我錯過了什麼?

stream.write(msg.length()); 
stream.write(msg.getBytes()); 

流是OutputStream

+0

你可以添加你實現的代碼,使遠嗎?目前我不知道什麼是錯的,你的描述中沒有足夠的信息。 – Mnementh 2010-04-20 14:35:30

回答

1

與您的實現有關的問題是,寫入方法只寫入一個字節,請參閱documentation。這裏的重要句子是:'b的24個高位被忽略。所以stream.write(msg.length());可能不會做什麼打算。 (我假設msg.length()返回一個int,糾正我,如果我錯了這裏。)

嘗試寫四個字節的整型:

stream.write(msg.length() % 256); 
stream.write((msg.length()/256) % 256); 
stream.write((msg.length()/(256 * 256)) % 256); 
stream.write((msg.length()/(256 * 256 * 256)) % 256); 

,首先寫最顯著字節,如果願意,您可以更改訂單。你也可以通過位移來完成字節轉換,對於我來說分區看起來更容易理解,但這是個人品味的問題。

+1

'&0xFF'和'>> 8'會比%256'和'/ 256'更合適,因爲它們更精確地顯示了意圖。但是'DataOutputStream'已經爲你做了這些:http://java.sun.com/javase/6/docs/api/java/io/DataOutputStream.html#writeInt%28int%29 – 2010-04-20 15:27:51

+0

好的提示與DataOutputStream 。這應該做的事情希望更平滑。 – Mnementh 2010-04-20 15:42:55

0

int在Java平臺的運行時沒有指定的字節排序,只是因爲沒有辦法直接觀察代表任何值的位模式。 但是方法,以某種方式將int(或其他)值轉換爲byte[]有一個定義的轉換。

因此,該值的正確發送/接收取決於從byte[]正確的編碼/解碼。只要你不告訴我們你如何做到這一步,我們就無法幫助你做到這一點。

1

看一下Int.reverseBytes()的方法,在x86平臺上這個方法會被打包到x86的bswapl操作碼上。

你可以調節這一關System.getProperty的結果( 「sun.cpu.endian」)

10
int htonl(int value) { 
    return ByteBuffer.allocate(4).putInt(value) 
    .order(ByteOrder.nativeOrder()).getInt(0); 
} 

或者

int htonl(int value) { 
    if (ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) { 
    return value; 
    } 
    return Integer.reverseBytes(value); 
} 
+0

這沒有更多upvotes?最清楚的答案! – kevinarpe 2016-01-25 12:53:28