Christian Eriksson Christian Eriksson - 18 days ago 8
Java Question

Why does my connection reset first time I try to write to Socket?

When I run my fairly simple TCP Server I notice that the first time I try to connect and send an object I get a connection reset error. If I keep the server running but let the client send again it all works. I'am at a loss here, what causes this behaviour?

Client:

for (int i = 0; i < 3; i++) {
Socket s = new Socket("192.168.0.10", 9750);
SysIO.print("Connected: " + s.isConnected());
ObjectOutputStream oos = new ObjectOutputStream(
new BufferedOutputStream(s.getOutputStream()));
Object obj = new OneMessage("Hi there: " + i);
oos.writeObject(obj);
oos.flush();

sleep(1000); // <-- turns error on and off :/
}


Server:

try (ServerSocket incomingSocket = new ServerSocket(mPort)) {
SysIO.print("Game Server started...");
incomingSocket.setSoTimeout(mTimeout);

while (mRunning) {
Socket clientConnection = null;
try {
clientConnection = incomingSocket.accept();
clientConnection.setSoTimeout(3000);

final Socket connection = clientConnection;
Thread requestHandlingThread = new Thread(() -> {
mRequestHandler.handleRequest(connection);
});
requestHandlingThread.start();

} catch (SocketTimeoutException ste) {
SysIO.print("TCP timeout...");
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (BindException ex) {
SysIO.print("Could not bind: " + ex.getMessage());
} catch (IOException ex) {
SysIO.print("There was a problem with IO in TCP Server: " + ex.getMessage());
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}


Request Handler:

public void handleRequest(Socket aRequest) {

try {
SysIO.print("Connected: " + aRequest.isConnected());
ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(aRequest.getInputStream()));
GameMessage message = (GameMessage) ois.readObject();

aRequest.close();


SysIO.print("Received: " + message.getType());
} catch (IOException | ClassNotFoundException ex) {
SysIO.print("IO exception: " + ex.getMessage());
Logger.getLogger(SimpleHandler.class.getName()).log(Level.SEVERE, null, ex);
}

}


I've tried closing and not closing the socket from the server after each request.

If I run the client without a loop it will seem to work, I thought it failed at first but I couldn't recreate it.

If I try to run the client in a loop all connections will fail the first time I run the client but if I then restart the client all will succeed.

Putting a sleep(1000) to pause a loop like above will make all connections succeed. Is it that simple that the Server can't handle quick connection attempts? I was hoping putting the request handling in separate threads would enable this. But why would the first connection in the loop also fail?

Regards,
Christian

Answer

So in the end I eneded up with something like this:

Client:

try {
    Socket connection = new Socket(mHostAddress, mHostPort);
    connection.setSoTimeout(mTimeOut);
    ObjectOutputStream outgoing = new ObjectOutputStream(
            new BufferedOutputStream(connection.getOutputStream()
            )); // <-- Opening output stream first in client (opposite to server)
    outgoing.writeObject(mMessage);
    outgoing.flush();
    outgoing.close(); // <-- closing the stream as per EJP's comment
} catch (IOException ex) {
    System.out.print("IOException in TCPSender: " + ex.getMessage());
}

Server:

ExecutorService pool = Executors.newFixedThreadPool(mClientThreads);
try (ServerSocket server = new ServerSocket(mPort)) {
    while (mRunning) {
        final Socket client = server.accept();
        client.setSoTimeout(mTimeOut);
        pool.execute(() -> {
            mMessageHandler.handle(client); // mMessageHandler = NetworkMessageHandler
        });
    }
} catch (IOException ex) {
    System.out.println("IO Exception occurred in TCPServer: "
            + ex.getMessage());
} finally {
    System.out.println("Server stopped...");
}

NetworkMessageHandler

try {
    ObjectInputStream input = new ObjectInputStream(
            new BufferedInputStream(aClient.getInputStream()) // Input first in server
    );
    NetworkMessage message = (NetworkMessage) input.readObject();
    input.close(); // <-- closing stream
    aClient.close(); // <-- making sure to close the Socket connection to client

    act(message, sendersIP); <-- acting on the message from client

} catch (IOException ex) {
    System.out.println("An IO exception occurred "
            + "in NetworkMessageHandler: " + ex.getMessage());
} catch (ClassNotFoundException ex) {
    System.out.println("Could not recreate the sent class: "
            + ex.getMessage());
}

I made sure that I didn't miss to close my streams and sockets and followed this oracle tutorial for someextra hints.

Regards, Christian