What is the right way to deal with terminated socket "client" - java

I have socket serve/client application. The "server" is waiting for data from "client", but if the client had been terminated the server throws EOFException.
Somewhere in the code in the server socket I have:
private ObjectInputStream in;
and somewhere I read the data:
in.readObject();
So should I just surround in.readObject(); in try-catch block or there is another solution?

If you look in the Javadoc API for ObjectInputStream.readObject, you'll see the list of exceptions
ClassNotFoundException - Class of a serialized object cannot be
found.
InvalidClassException Something is wrong with a class used by
serialization.
StreamCorruptedException Control information in the stream is inconsistent.
OptionalDataException Primitive data was found in the stream instead of objects.
IOException - Any of the usual Input/Output related exceptions.
IOException (which 99% of the time is a SocketException (subclass of IOException) is special case where your Socket has shutdown, so you should process this as if you have lost connection.
All of the other exceptions however indicate that your client is sending you something you aren't expecting. You should catch each of these Exceptions by name and send back a message saying that they need to update the client software version to the version that your server is ready to communicate with. Flush that message out, and then probably best to close the socket.

You can use like following. EOFException is a direct subclass of IOException. You should also catch IOException.
try{
....
in.readObject();
....
} catch(EOFException ex1){
// eof exception is thrown
} catch(IOException ex2){
// other types of IO exception is thrown
}

Related

Java Client Server - Exception Handling (Thread)

I wonder how to handle exceptions correctly within a client server application. My client sends an information to the server(thread) which receives it within its run method.
I have already read something about uncaught exception handling when dealing with exceptions in the run method but want to know if this is the correct way to do it in my case.
I want to catch the exception on the client side.
I have in mind to do the following:
//Server
run(){
try{
...
}
catch(Exception e){
clientoutputstream.write(...); //transmitting the error
}
}
Any other suggestions?
You should put a try { } catch (IOException) around your read() call so you know if the other end has closed the connection. The other thing you might want to do is to put a try { } catch(Throwable) { } around the processing code so you can manually close the socket (Be very careful about catching Throwable) But if you just let the thread die the Socket will be closed when the object is garbage collected or when it times out

Should I close the socket if setSoTimeout throw an exception?

Should i close the socket in finally block after setSoTimeout throws an Exception
try {
socket.setSoTimeout(4000);
//code for reading
} catch(java.lang.Exception ex) {
System.out.println(ex.toString());
} finally {
socket.close(); <-------is it necessary?
}
It depends on the actual exception, but you shouldn't write this method like this. The way you've written it, you will always close the socket. The close should be in the catch block, not the finally block.
Yes it is necessary.
Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound). A new socket needs to be created,
Closing this socket will also close the socket's InputStream and OutputStream.
you are probably thinking that when an exception is thrown the socket's resources are freed, but that isn't the case since socket.isClosed(); returns false if the exception is thrown, and generally always close the resource in the finally block because you don't really know whether an exception will be thrown or not, and its a good programming practice.

How to properly detect a client disconnect in servlet spec 3?

I have tried writing to the response, because there is no proper disconnect callback:
private boolean write(byte[] output, AsyncContext context) {
try {
OutputStream stream = context.getResponse().getOutputStream();
stream.write(output);
stream.flush();
return true;
} catch (IOException ex) {
//client disconnected
log.error(ex);
removeAsyncContext(context);
return false;
}
}
But this didn't seem to the trick. When the client is disconnected, writing and flushing the buffer did not throw an exception.
The weird thing is, the second time you try to write to the output stream (after the disconnect), the write does throw an exception. It looks like the first time you write/flush it,some internal state is set to error, without notifying.
I have tried on both Jetty 8 and Tomcat 7 and I see the same behavior.
Is there a solution to find out whether the message is received by the client? Am I missing something?
I recognize you are looking for a proper way of detecting disconnects, but for those who don't mind a kludge:
Note: This method periodically sends space characters to the client that must be trimmed before interpreting the results. This is the kludgey part.
Start a thread that has access to the writer/outputstream of the servlet response. This thread sends space characters periodically (I used 1 second intervals) to the client. Wrap in a IOException try/catch block that sets your abort flag.
If the connection is closed, most servlets will throw a flavor of EOFException (which is an IOException) when data cannot be delivered to the client. You are catching this exception and setting your abort flag.
When the abort flag is caught, you have options. You can nuke the executing thread, have all your processing periodically check for the abort flag, push an exception into the executing thread, or do any number of things (not detailed here).
Should the process finish successfully, you will get your results prefixed by a number of spaces. Again, remember to trim these on your client.
In my experience when a client disconnects from a servlet there is an exception referring to a Broken Pipe.
For example: Broken Pipe when writing bytes in ServletOutputStream
I would suggest catching java.net.SocketException and looking at the exception details to verify if it is a broken pipe (as a starting point):
Caused by: ClientAbortException: java.net.SocketException: Broken pipe
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:358)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:354)
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:381)
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:370)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89)

Detecting client disconnect in tomcat servlet?

How can I detect that the client side of a tomcat servlet request has disconnected? I've read that I should do a response.getOutputStream().print(), then a response.getOutputStream().flush() and catch an IOException, but is there a way I can detect this without writing any data?
EDIT:
The servlet sends out a data stream that doesn't necessarily end, but doesn't necessarily have any data flowing through it (it's a stream of real time events). I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera). If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
is there a way I can detect this
without writing any data?
No because there isn't a way in TCP/IP to detect it without writing any data.
Don't worry about it. Just complete the request actions and write the response. If the client has disappeared, that will cause an IOException: connection reset, which will be thrown into the servlet container. Nothing you have to do about that.
I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera).
There the finally block is for. It will be executed regardless of the outcome. E.g.
OutputStream output = null;
try {
output = response.getOutputStream();
// ...
output.flush();
// ...
} finally {
// Do your cleanup here.
}
If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
Depends on how you're reading from it and how much of request body is already in server memory. In case of normal form encoded requests, whenever you call getParameter() beforehand, it will usually be fully parsed and stored in server memory. Calling the getInputStream() won't be useful at all. Better do it on the response instead.
Have you tried to flush the buffer of the response:
response.flushBuffer();
Seems to throw an IOException when the client disconnected.

Can I have IO exception when I create a server socket in Java?

I have the following code:
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
The code is taken from a java.sun.com.
I have several questions concerning the above given short part of the code.
Why do we want to catch an IOException. I though that IOException is something that can happen when we use input-output methods (not networking methods).
What is the difference between the "System.err.println" and "System.println"?
In the catch statement we have "e". What for? Do we use it latter?
1: Why do we want to catch an IOException. I though that IOException is something that can happen when we use input-output methods (not networking methods).
Networking is also input/output. Byte streams through a socket.
2: What is the difference between the "System.err.println" and "System.println"?
The first writes to stderr, the second doesn't exist.
3: In the catch statement we have "e". What for? Do we use it latter?
To have a reference to the exception so that you can if necessary log or rethrow it.
(a) You aren't 'creating a server socket' in this code, you are accepting a Socket from a ServerSocket.
(b) That can fail for a lot of reasons including closure of the ServerSocket; running out of FDs; network stack problems; memory exhaustion; ... so it throws IOException.
One common reason for accept to throw an IOException is running out of file handles. It need two file handles to create the socket and if you run out you get an error like "Too many files open"

Categories