【问题标题】:C# to Java UTF8 string over TCP通过 TCP 的 C# 到 Java UTF8 字符串
【发布时间】:2021-03-31 19:17:45
【问题描述】:

由于客户端出现 EOF 错误,我无法将 UTF-8 字符串从 C# 服务器发送到 Java 客户端。如何正确配置 C# 服务器?我认为错误就在那里,因为这个客户端与下面显示的 Java 服务器一起工作。

Java 客户端的接收函数会这样做(如果我从 Java 服务器接收,这也可以工作,如下所示):

DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); //The constructor initialises a field, using the socket object.        
StringBuilder inputMessage = new StringBuilder();
inputMessage.append((String) dataInputStream.readUTF());

所需的 C# 服务器:

        static async Task Main(string[] args)
        {
            TcpListener server = new TcpListener(IPAddress.Any, 34567);
            server.Start();
            byte[] bytes = new byte[4096];
            byte[] responseBytes;
            using (var client = await server.AcceptTcpClientAsync()){
                using(var tcpStream = client.GetStream())
                {
                    await tcpStream.ReadAsync(bytes, 0, bytes.Length);
                    var playerNumber = Encoding.UTF8.GetString(bytes);
                    Console.WriteLine("Player " + playerNumber + " connected."); //java client to server works.

                    StringBuilder outputMessage = new StringBuilder("Some output");
                    responseBytes = Encoding.UTF8.GetBytes(outputMessage.ToString());
                    await tcpStream.WriteAsync(responseBytes, 0, responseBytes.Length); //This doesn't work...
                }
                server.Stop();
            }
        }

错误:

java.io.EOFException
    at java.base/java.io.DataInputStream.readFully(DataInputStream.java:201)
    at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:613)
    at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:568)
    at Client.Connection.Receive(Connection.java:26)
    at Client.Main.lambda$main$0(Main.java:30)
    at com.sun.javafx.application.PlatformImpl.lambda$startup$5(PlatformImpl.java:271)
    at com.sun.glass.ui.Application.invokeAndWait(Application.java:464)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runToolkit(QuantumToolkit.java:366)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$startup$10(QuantumToolkit.java:280)
    at com.sun.glass.ui.Application.lambda$run$1(Application.java:153)

有趣的是,Java 服务器 可以做到这一点:

            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            StringBuilder outputMessage = new StringBuilder("Some output");
            dataOutputStream.writeUTF(outputMessage.toString());
            dataOutputStream.flush();

编辑

这是从工作 Java 服务器接收的。 “bytearr”包含我用于消息的 100 个字节和 0 的 100 个字节(它们在我的消息之后)。 “chararr”正确地将前 100 个字节视为有意义的内容,将后 200 个字节视为“\u0000”:

这是从非工作 C# 服务器接收的。与正确版本相比,它似乎开始 两个字节,而且它的“chararr”仅包含数千个“\u0000”:

【问题讨论】:

  • 让我们忽略其他一切并从第一原则开始...正在接收哪些字节,除了哪些字节。它们有何不同。
  • 我不知道这是否与您所询问的问题直接相关,但忽略ReadAsync 的返回值是一个坏主意。如果您没有收到 4096 字节(即使写入了这么多字节,TCP 也不能保证所有这些字节都会同时到达,只是它们的顺序相同),那么 Encoding.UTF8.GetString 将解码缓冲区的所有 4096 字节,最后你会得到0s。使用该返回值!
  • 查看实际发送的内容。 Wireshark 可能很有用。
  • 在这种情况下,访问文档并检查您使用的方法和类是否真的应该按照您认为的那样做总是一个好主意。

标签: java c# networking utf-8 tcplistener


【解决方案1】:

DataInputStream 的readUTF 读取特殊 数据格式,它不是读取UTF-8 字节序列的通用方法。最值得注意的是,它需要一个指定流长度的初始字节序列。

【讨论】:

    【解决方案2】:

    我找到了答案here。将 Java 客户端的读取方式更改为此,可行:

    byte[] buff = dataInputStream.readAllBytes();
    String str = new String(buff, "UTF-8");
    

    【讨论】:

      猜你喜欢
      • 2014-01-01
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2012-07-22
      • 1970-01-01
      • 2012-10-14
      • 1970-01-01
      相关资源
      最近更新 更多