簡體   English   中英

如何通過Tcp將Java二進制流發送到C#?

[英]How to send a binary stream from Java to C# via Tcp?

我有一個c#服務器 我需要將Java客戶端連接到它,並使它交互。

以下是客戶端C#代碼:

string Host = "localhost";
int Port = 2000;

TcpClient Tcp = new TcpClient(Host, Port);

NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);

writer.Write("Hello");
string str = reader.ReadString();

該代碼的Java等效代碼是什么?

我寫了以下內容:

    InetAddress ip = InetAddress.getByName("localhost"); 

    int PORT_NO = 2000; 
    Socket socket = new Socket(ip, PORT_NO); 

    // obtaining input and out streams 
    DataInputStream reader = new DataInputStream(socket.getInputStream()); 
    DataOutputStream writer = new DataOutputStream(socket.getOutputStream());

    writer.writeChars("Hello");
    String str = reader.readUTF();

但是,我的Java代碼無法正常工作。

服務器正在運行。 服務器似乎未收到Java客戶端發送的字符串。

我該怎么做?

編輯:根據@van dench的建議,我在C#服務器中使用了以下代碼。 現在,甚至C#客戶端也停止工作。

寫...

            byte[] strBytes = Encoding.UTF8.GetBytes(str);
            byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
            Array.Reverse(lenBytes);
            writer.Write(lenBytes);
            writer.Write(strBytes);
            writer.Flush(); 

讀...

            byte[] lenBytes = reader.ReadBytes(4);
            Array.Reverse(lenBytes);
            int len = BitConverter.ToInt32(lenBytes, 0);
            byte[] bytes = reader.ReadBytes(len);
            string str = Encoding.UTF8.GetString(bytes);

Java的DataOutputStreamDataInputStream以稱為Modified UTF-8的格式編碼字符串。 這基本上意味着單個字符可以是1個,2個或3個字節長。 假定大多數人都將使用ASCII字符,則此方法旨在以更壓縮的方式編寫字符串。 編碼數據中的前導位用於確定此后是否還有另一個字節是同一字符的一部分。

盡我所能告訴C#的BinaryWriterBinaryReader只是對原始UTF-16數據進行編碼。

最簡單的解決方案是寫入字節數組而不是字符串。

在C#中,您將需要以下內容:

byte[] bytes = Encoding.UTF8.GetBytes(str);
writer.Write(bytes.Length);
writer.Write(bytes);  

int len = reader.ReadInt32();
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);

在Java中,您需要:

byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
writer.writeInt(bytes.length)
writer.write(bytes, 0, bytes.length);  

int len = reader.readInt();
byte[] bytes = new byte[len];
reader.read(bytes, 0, len);
String str = new String(bytes, StandardCharsets.UTF_8);

您可以根據需要將編碼更改為其他編碼,但是客戶端和服務器上的編碼必須相同。

編輯:

Java更喜歡Big Endian,而C#更喜歡Little Endian,因為這種長度之一必須顛倒。 鑒於網絡字節順序是大字節序,我建議在C#端執行此操作。

byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);

byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes);

問題是您在c#代碼中使用ReadString和Write方法。 他們使用Java不知道的長度前綴格式。

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.binarywriter.write?redirectedfrom=MSDN&view=netframework-4.8#System_IO_BinaryWriter_Write_System_String_

長度前綴表示在使用BinaryWriter實例的當前編碼對流進行編碼時,此方法首先將字符串的長度(以字節為單位)寫入。 此值寫為無符號整數。 然后,此方法將那么多字節寫入流中。

例如,字符串“ A”的長度為1,但是使用UTF-16編碼時則為0。 長度為2個字節,因此寫在前綴中的值為2,並將3個字節(包括前綴)寫入流中。

https://docs.microsoft.com/zh-cn/dotnet/api/system.io.binaryreader.readstring?view=netframework-4.8

暫無
暫無

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

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