It was silly of me not to dump the stuck trace while catching the IOException from socket.accept() and shutting down the thread doing the accept... Having fixed this, I still want to understand how to deal with the situation when this call barfs.
My app is a classic socket server accepting hundreds of clients, sometimes thousands. Accepting thread is always up and blocked in accept() call. Once accepted, the separate thread gets launched to do the stuff and so on. Nothing special.
The question is, what should be done when accept() fails? Should this be considered as a permanent failure immediately? Should I retry to get into accept() for some time and try to get through? What's the best practice? And what normally the reasons for the IOException to be thrown?
Its the clients responsibility to retry on connection failure. The server should just log the exception and continue back doing "accept". Servers in general, never initiate connections to client.
There are too many reasons for IOException to be thrown, from firewall issues to file-handle-exhaustion issues. The message of the IOException should reveal the cause.
The only reasons I can think of for an IOException being thrown in accept() call would be some issue with the port being in use or the host's networking being misconfigured.
You could potentially wait a bit and retry on the assumption that the system's administrator will notice the problem and fix it. But if this happens during startup, it would be a good idea for the application to bail out with a "fatal" error message.
Related
The answer, here, by Stephen C very well describes the issue. He says Broken pipe exception is caused by something causing the connection to close, and its not the application. I want to know what all this "something" could be in general, which is causing the connection to close? And what are the possible ways to handle them?
My usage environment:
I am running my application on set of machines on Azure, and all of them are talking to one of the machine. I am getting this error almost always.
Could TCP timeout be one of the reasons? If yes then how to make Socket Channels(in affect Socket running behind them) never close dues to TCP timeout?
You can get the socket associated with SocketChannel and then set its keepAlive property. Something like this.
SocketChannel sockChannel;
/*
connect here
*/
sockChannel.socket().setKeepAlive(true);
Broken pipe exception comes whenever client moves away from the socket on which it is listening. This might be due to socket timeout reached on client side as server was responding slow. Say, in case of a browser if any http request is taking long to respond and user closes the browser a broken pipe exception will be visible in application logs.
Now to resolve this either you increase socket timeout or fix you server response.
Is there any way of preventing my application from temporarily crashing as soon as I create a socket? This program unfreezes as soon as it receives a connection but it can be misleading to users.
I have tried putting the socket creation methods etc. in a thread and running it from there but that did not work.
Edit: Unless it would be feasible to give the socket a set amount of time and then disconnect once it expires?
Running it in a separate thread is the right way, since the Socket.accept() call is blocking (i.e. it blocks the thread you call it on, until it gets a connection).
There must be something wrong with your thread architecture. Post some code and maybe I can tell You what exactly.
EDIT: Giving the socket a short timeout will either not avoid the blocking, or timeout before someone connects, while getting a connection before the timeout will not have any difference from the current setup.
You program does not crash, it is simply waiting for a connection because the java.io library is blocking.
To prevent waiting for a connection, you can either use the non-blocking java.nio classes or start a new Thread and let this new thread be the one that is waiting for the connection.
The documentation says that Socket's setSoTimeout(int) method
throws SocketException - if there is an error in the underlying protocol, such as a TCP error
Have you ever caught this exception? When using TCP sockets, what kind of TCP error could make this method throw the exception?
EDIT:
Let me try to be a bit more specific and deeper. I'm not looking for the trivial (eg, a closed socket will throw this exception) that can be easily found elsewhere.
Suppose the Socket (representing a TCP connection) has just been created, is connected, and not yet closed. I've not yet performed any reads/writes on it. I'm running on Linux (Ubuntu Server 11.04), so we can forget the case in which the TCP implementation doesn't support read timeouts.
Now, can this exception be thrown in this situation? If so, what does it mean? Is it something specific to the current Socket instance? If I simply close() it and somehow obtain a new one, should it work? Is it a bigger problem I cannot recover from (such as a problem in the operating system), and should better shutdown my application?
The SocketException, in this scenario, is either thrown if the socket is closed or closing.
It can also be thrown to indicate an error that was generated by the native TCP stack implementation. If, for instance, you are on Windows, setSoTimeout will likely boil down to an invocation of the setsockopt function in the Windows Winsock API. An error from this method would indicate some deeper issue in the winsock subsystem (unable to initialize) or it could also be thrown if you attempt to set socket options when a blocking operation is in progress on the socket (by another thread, for instance). For this reason, you should strive to only modify socket options at creation time, avoiding to change any options once you've connected the socket and started doing I/O on it.
You can read more here if you are curious.
java.net.SocketExceptionis thrown when you call setSoTimeout on a closed socket.
As always, use the forc..source.
While i am running my program i have svrSocket.accept() method..My program is automatically getting terminated when it reaches to svrSocket.accept() method.
Please suggest what needs to be done.
Here is what you need to provide before we can really help you.
Stacktraces for exceptions that accept() might be throwing. If this is a simple console application look for those in the console of your IDE. There is a separate window that it runs in and shows output like this.
Is the program truly terminating? accept() is a blocking call and blocks forever until another process connects to it through the socket. Have you tried running a client that connects to your server socket to see if it un blocks and continues to run? If you have to click the stop button, if multiple run windows are open then your program is simply blocked on the accept() call and it's working as designed.
Without example code or an error message for reference, according to the API, your application may not be catching one of the following exceptions:
IOException
SecurityException
SocketTimeoutException
IllegalBlockingModeException
Also, are you sure your application terminates? The only reason I ask is accept() blocks until a connection is made.
I have a single-threaded non-blocking socket IO server written in Java using nio.
When I have finished writing to a connection, I want to close it.
Does the closing of the channel mean blocking until all buffered writes have been acknowledged by the recipient?
It would be useful to know if, when asynchronously closing, it succeeded or not, but I could live with any errors in the closing being ignored.
Is there any way to configure this, e.g. with setSoLinger() (and what settings would be appropriate?)
(A general discussion beyond Java about Linux and other OS in this respect would be useful to)
Closing in non-blocking mode is non-blocking.
You could put the channel into blocking mode, set a positive linger timeout, and close, and that would block for up to the linger timeout while the socket send buffer was being emptied, but alas Java doesn't throw an exception if the linger timeout expires, so you can't know whether all the data has gone. I reported this bug ten or more years ago and it came back 'will not fix' because of compatiblity concerns. If you can wait until Java 7 comes out I believe the nio2 stuff has this fixed, I certainly requested it, but who knows when that will be?
And even if you have all that, all you know is that the data was sent. You don't know anything about it being received or processed by the recipient application. If you need that you have to build it into your application protocol.
I'm not sure what really happens but I know that close() includes flush() (except in PrintStream and PrintWriter...).
So my approach would be to add the connections to close to a queue and process that queue in a second thread (including error handling).
I understand that your server is single-threaded but a second thread doesn't cost that much, the complexity of the problem is low and the solution will be easy to understand any maintain.