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.
Related
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
}
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
For years I've been wondering what the correct way to close a listening ServerSocket in Java is. My implementations always work like this, they:
Create a new ServerSocket(int).
Start a thread that calls its accept() method in a while (true) loop.
Start another thread when accept() returns (client connects) that reads from the client until it disconnects. The accept thread then continues with another accept() call.
But when I want to close the ServerSocket because my application is exiting, I've never found another way of doing so other than calling it's close() method (after I've closed all client Sockets), which causes accept() to throw a SocketException, I catch that and break from the while (true) loop in the accept thread, causing all my threads to exit.
I think this is ugly, strictly speaking there is no exception occurring, closing my ServerSocket is part of my programs normal operation.
Is there really no other way of doing this without causing an Exception to be thrown?
Thanks.
I've never found another way of doing so other than calling it's close() method (after I've closed all client Sockets),
You can set a flag closed = true; and open a dummy connection to wake up the accept()ing thread which checks the flag before continuing.
which causes accept() to throw a SocketException,
A SocketClosedException which is expected behaviour here.
I catch that and break from the while (true) loop in the accept thread,
If you catch it outside the loop, you don't need to also break out of the loop. If the exception is thrown and you have set closed = true you can discard the exception.
BTW I would do
while(!serverSocket.isClosed()) {
causing all my threads to exit.
There is no particular reason you need to have this, but you can choose to do this if you want.
I think this is ugly, strictly speaking there is no exception occurring,
An exceptional condition is happening. What is not happening is an Error.
closing my ServerSocket is part of my programs normal operation.
Or you could say it is operating normally when it is running and not shutting down.
Thanks for your comment.
You can set a flag closed = true; and open a dummy connection to wake up the accept()ing thread which checks the flag before continuing.
Opening a new Socket to close an existing one? IMO that is one of the worst sins ever.
A SocketClosedException which is expected behaviour here.
Actually it doesn't throw a SocketClosedException but a SocketException, the following code:
try {
final ServerSocket ss = new ServerSocket(1234);
new Thread(new Runnable() {
#Override
public void run() {
try {
ss.accept();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
ss.close();
} catch (Exception ex) {
ex.printStackTrace();
}
Produced the following output:
java.net.SocketException: Socket is closed
at java.net.ServerSocket.accept(ServerSocket.java:494)
at Main$1.run(Main.java:12)
at java.lang.Thread.run(Thread.java:744)
If you catch it outside the loop, you don't need to also break out of the loop. If the exception is thrown and you have set closed = true you can discard the exception.
BTW I would do
while(!serverSocket.isClosed()) {
That would work, but I think this should work without setting flags and catching Exceptions.
An exceptional condition is happening. What is not happening is an Error.
Or you could say it is operating normally when it is running and not shutting down.
I don't agree. It is normal behaviour for applications to be exiting. They may always do so.
Why doesn't the accept() method just returns null when close() is called? That would be so much easier.
Basically I want to create a rock solid server.
while (keepRunning.get()) {
try {
Socket clientSocket = serverSocket.accept();
... spawn a new thread to handle the client ...
} catch (IOException e) {
e.printStackTrace();
// NOW WHAT?
}
}
In the IOException block, what to do? Is the Server socket at fault so it need to be recreated? For example wait a few seconds and then
serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT);
However if the server socket is still OK, then it is a pity to close it and kill all previously accepted connections that are still communicating.
EDIT: After some answers, here my attempt to deal with the IOException. Would the implementation be guaranteeing keeping the server up and only re-create server socket when only necessary?
while (keepRunning.get()) {
try {
Socket clientSocket = serverSocket.accept();
... spawn a new thread to handle the client ...
bindExceptionCounter = 0;
} catch (IOException e) {
e.printStackTrace();
recreateServerSocket();
}
}
private void recreateServerSocket() {
while (keepRunning) {
try {
logger.info("Try to re-create Server Socket");
ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT);
// No exception thrown, then use the new socket.
serverSocket = socket;
break;
} catch (BindException e) {
logger.info("BindException indicates that the server socket is still good.", e);
bindExceptionCounter++;
if (bindExceptionCounter < 5) {
break;
}
} catch (IOException e) {
logger.warn("Problem to re-create Server Socket", e);
e.printStackTrace();
try {
Thread.sleep(30000);
} catch (InterruptedException ie) {
logger.warn(ie);
}
}
}
}
If in doubt, you could try re-creating the server socket, using the same port. If the socket has been closed, then the creation will succeed and you can continue processing new connections. The old connections are gone, but that's outside of your control since the socket was closed. If the socket was not closed, then creating a new instance will fail since the port is still in use, which you can just ignore - i.e. don't replace the current server socket reference.
In general, clients should also assume that connections will be broken and that reconnection is necessary. In other words, it's not just the server that has to be robust - clients should also anticipate connection errors and reconnect.
You can get an IOException on an accept() if the server socket is closed (by you) or you run out of resources, e.g. file handles. Either way, there is not much you can do about it. If the serverSocket is closed (you can test for this) you probably had a good reason to do this. If you run out of resources, you will either have to increase your resource limit, which requires a restart of your application, or you have a resource leak.
Make sure you differentiate between different IOExceptions you might receive. Is it an exception on creating a connection? Is it an exception once a connection has already been established?
The only code you gave is for accept()ing. Generally speaking, an IOException usually means an error on any layer on the physical network.
Probably the best fallback behavior you can implement is to wait for a certain time quantum, and then try to reconnect. Assume you most possibly will not be able to reconnect, since you have lost network connection for more than a temporary period. Make sure you handle this gracefully. As #mdma mentioned, this must be supported by your clients as well.
However if the server socket is still
OK, then it is a pity to close it and
kill all previously accepted
connections that are still
communicating.
Please note that closing the server socket will NOT close previously accepted connections. As soon as a connection has been accepted it lives a separate, joyful life at a different port.
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"