簡體   English   中英

從C#客戶端向Java服務器發送4字節消息頭

[英]Sending a 4 byte message header from C# client to a Java Server

我正在嘗試將C#客戶端編寫到用Java編寫的服務器上。 服務器需要一個4字節(Java中的DataInputStread readInt())消息頭,后跟實際消息。

我是C#的新手,如何將此消息頭發送到Java Server? 我嘗試了幾種方法(主要是試驗和錯誤,而沒有深入到C#語言),沒有任何效果。 Java端最終得到了錯誤的(非常大的)消息長度。

正如其他海報所指出的那樣,它一直是字節序。

Java DataInputStream期望數據是big-endian (網絡字節順序)。 從Mono文檔(對於像BinaryWriter這樣的等價文件)來看,C#傾向於小端(Win32 / x86的默認值)。

因此,當您使用標准類庫將32位int'1'更改為字節時,它們會產生不同的結果:

//byte hex values
Java: 00 00 00 01
  C#: 01 00 00 00

您可以改變在C#中編寫int的方式:

private static void WriteInt(Stream stream, int n) {
    for(int i=3; i>=0; i--)
    {
        int shift = i * 8; //bits to shift
        byte b = (byte) (n >> shift);
        stream.WriteByte(b);
    }
}

編輯:

更安全的方法是:

private static void WriteToNetwork(System.IO.BinaryWriter stream, int n) {
    n = System.Net.IPAddress.HostToNetworkOrder(n);
    stream.Write(n);
}

這很簡單,但你檢查了字節順序嗎? 您發送數據的字節順序與您收到的字節順序之間很容易不匹配。

正如這里的每個人都已經指出的那樣,問題很可能是由於C#應用程序以小端順序發送整數,而Java應用程序期望它們按網絡順序(big-endian)。 但是,不是在C#app中明確重新排列字節,而是正確的方法是依靠內置函數將主機轉換為網絡順序(htons等) - 這樣你的代碼即使在運行時也能繼續正常工作在一台大端機器上。

通常,在對這些問題進行故障排除時,我發現使用netcat或wireshark等工具記錄正確的流量(例如,Java中的Java)很有用,然后將其與不正確的流量進行比較,以查看它出錯的地方。 作為額外的好處,您還可以使用netcat將捕獲/預先記錄的請求注入服務器或將捕獲/預先記錄的響應注入客戶端。 更不用說您還可以修改文件中的請求/響應,並在開始修復代碼之前測試結果。

如果您要交換大量數據,我建議實現(或查找)可以按網絡順序寫入和讀取整數的Stream-wrapper。 但如果你真的只需要寫長度做這樣的事情:

using(Socket socket = ...){
  NetworkStream ns = new NetworkStream(socket);      
  ns.WriteByte((size>>24) & 0xFF);
  ns.WriteByte((size>>16) & 0xFF);
  ns.WriteByte((size>>8)  & 0xFF);
  ns.WriteByte( size      & 0xFF);
  // write the actual message
}

我不知道C#,但你只需要做相同的事情:

out.write((len >>> 24) & 0xFF);
out.write((len >>> 16) & 0xFF);
out.write((len >>>  8) & 0xFF);
out.write((len >>>  0) & 0xFF);

Sysetm.Net.IPAddress類有兩個靜態輔助方法:HostToNetworkOrder()和NetworkToHostOrder()為您進行轉換。 您可以在流上使用BinaryWriter來寫入正確的值:

using (Socket socket = new Socket())
using (NetworkStream stream = new NetworkStream(socket))
using (BinaryWriter writer = new BinaryWriter(stream))
{
    int myValue = 42;
    writer.Write(IPAddress.HostToNetworkOrder(myValue));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM