简体   繁体   English

如何通过Tcp将Java二进制流发送到C#?

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

I have a c# server . 我有一个c#服务器 I need to connect a Java client to it, and make it interact. 我需要将Java客户端连接到它,并使它交互。

The following is a client-side C# code: 以下是客户端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();

What would be the Java equivalent of this code? 该代码的Java等效代码是什么?

I have written the following: 我写了以下内容:

    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();

But, my java code isn't working. 但是,我的Java代码无法正常工作。

Server is running okay. 服务器正在运行。 The server seems to be not receiving the string sent by Java client. 服务器似乎未收到Java客户端发送的字符串。

How can I do what I need? 我该怎么做?

.

Edit: I used the following code in C# server according to @van dench 's suggestion. 编辑:根据@van dench的建议,我在C#服务器中使用了以下代码。 Now, even C# clients stopped working. 现在,甚至C#客户端也停止工作。

write... 写...

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

read... 读...

            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's DataOutputStream and DataInputStream encode strings in a format known as Modified UTF-8. Java的DataOutputStreamDataInputStream以称为Modified UTF-8的格式编码字符串。 This basically means that a single character can be either 1, 2, or 3 bytes long. 这基本上意味着单个字符可以是1个,2个或3个字节长。 It is intended to write strings in a more compressed manor assuming that most people will be using ASCII characters. 假定大多数人都将使用ASCII字符,则此方法旨在以更压缩的方式编写字符串。 The leading bit in the encoded data is used to determine if there is another byte afterwards that is part of the same character. 编码数据中的前导位用于确定此后是否还有另一个字节是同一字符的一部分。

As best I can tell C#'s BinaryWriter and BinaryReader just encodes the raw UTF-16 data. 尽我所能告诉C#的BinaryWriterBinaryReader只是对原始UTF-16数据进行编码。

The easiest solution is going be write a byte array instead of a string. 最简单的解决方案是写入字节数组而不是字符串。

In C# you're going to need the following: 在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);

and in Java you will need: 在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);

You can change the encoding to something else if you wish, but it has to be the same on the client and the server. 您可以根据需要将编码更改为其他编码,但是客户端和服务器上的编码必须相同。

Edit: 编辑:

Java prefers Big Endian while C# prefers Little Endian, because of this one of the lengths has to be reversed. Java更喜欢Big Endian,而C#更喜欢Little Endian,因为这种长度之一必须颠倒。 Given that network byte order is big endian I would recommend doing this on the C# side. 鉴于网络字节顺序是大字节序,我建议在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);

The problem is that you are using ReadString and Write methods in your c# code. 问题是您在c#代码中使用ReadString和Write方法。 They use a length-prefixed format that Java has no idea about. 他们使用Java不知道的长度前缀格式。

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

Length-prefixed means that this method first writes the length of the string, in bytes, when encoded with the BinaryWriter instance's current encoding to the stream. 长度前缀表示在使用BinaryWriter实例的当前编码对流进行编码时,此方法首先将字符串的长度(以字节为单位)写入。 This value is written as an unsigned integer. 此值写为无符号整数。 This method then writes that many bytes to the stream. 然后,此方法将那么多字节写入流中。

For example, the string "A" has a length of 1, but when encoded with UTF-16; 例如,字符串“ A”的长度为1,但是使用UTF-16编码时则为0。 the length is 2 bytes, so the value written in the prefix is 2, and 3 bytes are written to the stream, including the prefix. 长度为2个字节,因此写在前缀中的值为2,并将3个字节(包括前缀)写入流中。

https://docs.microsoft.com/en-us/dotnet/api/system.io.binaryreader.readstring?view=netframework-4.8 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