[英]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.