0

I'm unable to send a UTF-8 string from a C# server to a Java client due to an EOF error in the client. How do I properly configure the C# server? I assume the error lies there because this client works with the Java server shown below.

Java client's receive function does this (this also works if I receive from a Java server, shown below):

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

Desired C# server:

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

The error:

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)

Interestingly, a Java server doing this works:

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

EDIT

This is received from the working Java server. The "bytearr" contains 100 bytes that I am using for my message and 100 bytes that are 0 (they come after my message). The "chararr" correctly sees the first 100 bytes as something meaningful and the last 200 bytes as '\u0000': enter image description here enter image description here

This is received form the non-working C# server. It seems to start two bytes in compared to the correct version and also it's "chararr" contains only thousands of '\u0000': enter image description here enter image description here

4
  • 4
    lets ignore everything else and start from first principles... What bytes are being received, what bytes do you except. How do they differ. Commented Dec 22, 2020 at 3:04
  • 3
    I don't know if this is directly related to the problem you're asking about, but ignoring the return value of ReadAsync is a bad idea. If you don't receive 4096 bytes (even if that much was written, TCP doesn't guarantee all of it will arrive at the same time, just that they'll be in the same order), then Encoding.UTF8.GetString is going to decode all 4096 bytes of the buffer and you'll get 0s at the end. Use that return value! Commented Dec 22, 2020 at 3:08
  • 1
    Look at what is actually sent. Wireshark may be useful. Commented Dec 22, 2020 at 3:32
  • 1
    In such cases, it's always a good idea to hit the docs and check if the methods and classes you are using are actually supposed to be doing what you think they are doing. Commented Dec 22, 2020 at 7:51

2 Answers 2

3

DataInputStream's readUTF reads a special data format, it is not a general purpose method for reading a sequence of UTF-8 bytes. Most notably, it expects an initial sequence of bytes specifying the length of the stream.

Sign up to request clarification or add additional context in comments.

Comments

1

I found the answer here. Changing the way the Java client reads to this, works:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.