1

I am trying to set up a program where the server can communicate with multiple clients. The program is written in Java. I got it all working on the same machine so I decided to try LAN. I converted the program to JAR files and I tried connecting my laptop to my PC (both are on the same network). The connection is successful but unfortunately only 1 message arrives to the server. As you can see in the code below, I send multiple messages (Meaning that i write multiple times) via DataOutputStream. One defines the datatype (in the following example 0 means that it's a String) and the other sends the actual message data. I also print the size of the packets in bytes and it always matches the size of the DataOutputStream instance.

DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
String str = "Hello";
//Type
System.out.println("Type output size: 1");
dOut.writeByte(0);
//Message
System.out.println("Message output size: " + (str.getBytes(StandardCharsets.UTF_8).length + 2));
dOut.writeUTF(str);

System.out.println("Length of all: " + (dOut.size()));
dOut.flush();

So now when the data from the client is sent we need to handle it on the server, which the code below does. It retrieves the InputStream from the Socket called client and inserts it into the DataInputStream. This is were it gets weird on LAN as the stream only contains the first message.

InputStream stream = client.getInputStream(); 
DataInputStream dIn = new DataInputStream(stream); 

while(dIn.available() > 0) {
   byte type = dIn.readByte();
    
  switch(type) {
                    
    case 0:
      System.out.println(dIn.readUTF());
      break;
    case 1:
      System.out.println(dIn.readInt());
      break;
    case 2:
      System.out.println(dIn.readByte());
      break;

    default:
      throw new IllegalStateException("Unexpected value: " + type);       
  }
}

If you run the Client in the IDE on lets say a laptop connected to the same network and then you run the Server on a PC connected to the same network it will work. However, not if the programs are in JARS.

The actual stacktrace is the following:

java.net.SocketException: Connection reset at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:323) at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350) at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803) at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966) at java.base/java.net.Socket$SocketInputStream.read(Socket.java:961) at java.base/java.io.DataInputStream.readInt(DataInputStream.java:393)

The stacktrace does not tell me anything, but it points at case 0: in the switch case. It can't read the String as the DataInputStream does not contain any data (I guess?).

I would also like to state that the Server is multithreaded! I have one thread that adds the sockets when they are accepted through ServerSocket.accept() and I use the second (main thread) to read the data sent from clients.

I have selected the code above as I believe that the issue lies within it, however I am new to Socket Programming and I know that some of you would like to see other parts of the code. I will add more relevant code when I am asked.

I do not know why it acts like this, does anyone know why?

What have i tried?

  • I have tried waiting for packets - but that has only resulted in the Server looping forever. With waiting for packets I mean not going forward until the DataInputStream contains enough bytes.
  • I have disabled Nagels Algorithm through setTCPNoDelay(false).
  • Tried to send different datatypes, but that also failed
  • I tried changing the first packet to a String which resulted in the String showing up in the DataInputStream.
  • I have tried portforwarding the port used and I have tried disabling the firewall on both computers.

Update 1

I have been taking advice from the comments which has led a to a few discoveries:

  • Closing the DataOutputStream successfully sends all packets to the client.
  • It is also possible to build your own buffer and decode it in the server. However, it is still not possible to send any more messages after this.
  • It worked as a JAR because IntelliJ was being nice (Eclipse threw the same error when running in IDE)

Update 2: I think this post is relevant. It states that SocketException is sent when a client closes it's socket "ungracefully". And because my Client closes (as it is not in a loop) and I don't close the socket properly - it will close "ungracefully" and the data will be lost. Hence the error.

Dubstepzedd
  • 148
  • 1
  • 9
  • You are reading from the input stream *while data is available*. So if you read the first pkg before the second one arrives, your program thinks there are no more data. Find another way to terminate the data stream. – Burak Serdar Nov 26 '21 at 21:14
  • Please do not post links to repositories and expect people to download and build your code. Please read [**How to create a Minimal, Reproducible Example**](https://stackoverflow.com/help/minimal-reproducible-example) and then do just that. – Andrew Henle Nov 26 '21 at 21:16
  • I didn't know that was against the rules. @AndrewHenle – Dubstepzedd Nov 26 '21 at 21:30
  • As stated in the "What have I tried", I have tried limiting it. The second package never arrives somehow. I limited it with the available() method. @BurakSerdar – Dubstepzedd Nov 26 '21 at 21:31
  • re *As you can see in the code below, I send multiple messages via DataOutputStream* -- actually, no, I can't see that. I see only one message being sent, and it **appears** to use a new DataOutputStream for that one message. Are you creating a new stream each time? – user16632363 Nov 26 '21 at 21:36
  • With multiple messages I mean that I "write" multiple times. Maybe that is misleading? The code that you see is only run once. @user16632363 – Dubstepzedd Nov 26 '21 at 21:38
  • I don't close the stream as I might want to send more messages after that one. – Dubstepzedd Nov 26 '21 at 21:39
  • Is there a difference in the used jvm in eclipse and the installed version, which executes the jars? – Sowasvonbot Nov 26 '21 at 21:51
  • I actually use IntelliJ, but I will try running it with Eclipse to see if there is a difference. How can I see what version executes the JAR? Is that in my JAVAPATH? – Dubstepzedd Nov 26 '21 at 23:40
  • Switching from IntelliJ to Eclipse caused the error on the Laptop in the IDE as well. – Dubstepzedd Nov 26 '21 at 23:56
  • I updated the question with additional information – Dubstepzedd Nov 27 '21 at 01:08
  • In your client code the 'main' function calls sendData and then exits without knowing that the data have been received by the server. This smells like it could introduce a race hazard. – user16632363 Nov 27 '21 at 03:14
  • I can make the server send back a message, however, what should I do when it was not recieved? If I send another message that wont be recieved either… I wonder why it does not send all data until the stream is closed. – Dubstepzedd Nov 27 '21 at 10:14

1 Answers1

1

The issue is now solved, and the solution is quite logical. My client does not operate in a loop, rather it sends the data and closes the program. That sounds fine, but I forgot to properly close the socket of the client.

The reason why the second 'packet' never arrived was due to me doing this tiny mistake. The packet was on it's way through the local network but the client socket improperly closed it's socket before the packet arrived to the server, which is why I got a SocketException error. See this.

I solved the issue by putting socket.close() ,where socket is the client's socket, after I had sent all the messages I wanted to send.

Dubstepzedd
  • 148
  • 1
  • 9