0

I have just started working with sockets and I am not a very experienced programmer. I would like to close the connection on client side by the use of a disconnect button. The disconnect button would execute the following code:

 private void closeConnection() {
    if (socket != null) {
        jLabelStatus.setText("Status: closing connection");
        try {
            socket.close();
        } catch (IOException ex) {
            Logger.getLogger(DatabaseClient.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            socket = null;
        }
    }
}

However, I am not very sure how I can assure that no exceptions turn up on the server side. My run() method (which overrides Runnable run() method) executes the following code as part of finally block on catching an exception when trying to read messages:

try {
    threadSays("Lost connection to client.");
    socket.close();
} catch (IOException ex) {
    Logger.getLogger(ClientHandlerThread.class.getName()).log(Level.SEVERE, null, ex);
}

Here is when, if I do press the disconnect button, the server throws a SEVERE: null java.io.EOFException.

I understand that this might be because... I am trying to do socket.close() here, even though it's been done in the client. So what would be the best way to assure no exception occurs? Is the socket.close() method not required if socket.close() occurs in the client? How do I check if it has occurred?

Edit: Stack Trace

SEVERE: null
java.io.EOFException
    at java.base/java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:3062)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1561)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)
    at sqlitechinookcw.ClientHandlerThread.run(ClientHandlerThread.java:64)
    at java.base/java.lang.Thread.run(Thread.java:830)
user207421
  • 305,947
  • 44
  • 307
  • 483
Papbad
  • 163
  • 2
  • 13
  • Send a `DISCONNECT` to the server. It currently expects ***something*** from the client. And instead of ***something*** the client just hangs up. So, either send a "goodbye" or just ignore that specific exception (BOSS! they hung up!) – Elliott Frisch Mar 27 '20 at 01:49
  • No. Closing the socket already sends a disconnect at the TCP level. There is no need to add an additional application protocol message for this. The `EOFException` here is expected behaviour; and the application needs to cope with it anyway in case the sender failed to send the DISCONNECT message. @ElliottFrisch – user207421 Mar 27 '20 at 03:26
  • @user207421 That was the gist of the "BOSS! they hung up!" part. And agreed, the behavior is expected at the implementation level. However, exceptions should be exceptional. So having an explicit goodbye to indicate client intent is not inherently bad (regardless of the wire protocol also having a termination mechanism). – Elliott Frisch Mar 27 '20 at 04:29
  • @ElliottFrisch I have never bought this stuff about 'exceptional', not using exceptions for flow control, etc. The fact is (a) that the API throws the exception, there having been no other practical way to design it, so you have to catch it, and (b) that it is an infallible indication of an orderly peer disconnect, which is why you don't need another, fallible, one. – user207421 Mar 27 '20 at 04:45
  • @user207421 The issue is usually one of keep-alive. You want to avoid the "expensive" tcp socket connect (or at least amortize it). If your protocol doesn't include an explicit "goodbye" you end up with hack-y solutions to implement multiple-requests with keep alive (like HTTP). – Elliott Frisch Mar 27 '20 at 04:47
  • @ElliottFrisch Application protocol DISCONNECT messages don't have anything to do with keepalive either. That would be a different message. – user207421 Mar 27 '20 at 04:52
  • @ElliottFrisch We don't need any information about the OP's application protocol to know that `EOFException` is entirely sufficient for the task it does, both here and elsewhere. But this dicussion ends like all the others I've had here on this topic: my cogent arguments remain unanswered, my cogent objections ditto, and all I get instead is slogans and subject-changing. Only serves to reinforce my absolute conviction that the objection to `EOFException` and so forth is just a phobia. – user207421 Mar 27 '20 at 06:26
  • @user207421 Throwing an exception involves populating a stack trace, which can take on the order of ~80 ms. It's a small cost. But multiply by 100k concurrent connections. And it's not so small. Now scale the application to support multiple request-response cycles. And the problem is not trivial. Now, your "cogent" arguments and objections seem to be "you can pay that cost, shut-up". – Elliott Frisch Mar 27 '20 at 14:03

1 Answers1

1

An exception is expected behavior in this situation. Your server's run() method is calling ObjectInputStream.readObject(), which can't return a partial object. A disconnect would be a fatal error. Just let it happen, and catch the exception so your server can close() its side of the connection and exit from run().

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770