This question already has answers here:
How can a socket be both connected and closed?
(1 answer)
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 9 years ago.
I would have assumed that calling isConnected() on a socket would tell me whether if is connected to the other side or not.
Returns: true if the socket successfuly connected to a server
but after checking and then calling flush() on the socket I get
java.net.SocketException: Broken pipe
How is isConnected different than isClosed, and what is the real behavior of each?
How do I tell if the other side if officially closed without writing anything to the streams, or creating new connections? Is there even a way?
I would have assumed that calling isConnected() on a socket would tell me whether if is connected to the other side or not.
Wrong. It tells you whether you ever connected this Socket. It doesn't tell you about the state of the connection.
Returns: true if the socket successfuly connected to a server
Note that it doesn't say 'is currently connected' to a server.
How is isConnected different than isClosed, and what is the real behavior of each?
The real behaviour of both is that they tell you what you have done to the socket, not what the state of the connection is.
How do I tell if the other side if officially closed without writing anything to the streams, or creating new connections? Is there even a way?
No there isn't. If the peer closed normally, a read will return an EOS indication (read() returns -1, readLine() retuns null, readXXX() for any other XXX throws EOFException). A write will throw an IOException 'connect reset' or 'broken pipe' depending on your platform. TCP doesn't support anything in the nature of a 'dial tone', so absent a pending write there is no current connection status to enquire on.
Related
I am running into some issues with the Java socket API. I am trying to display the number of players currently connected to my game. It is easy to determine when a player has connected. However, it seems unnecessarily difficult to determine when a player has disconnected using the socket API.
Calling isConnected() on a socket that has been disconnected remotely always seems to return true. Similarly, calling isClosed() on a socket that has been closed remotely always seems to return false. I have read that to actually determine whether or not a socket has been closed, data must be written to the output stream and an exception must be caught. This seems like a really unclean way to handle this situation. We would just constantly have to spam a garbage message over the network to ever know when a socket had closed.
Is there any other solution?
There is no TCP API that will tell you the current state of the connection. isConnected() and isClosed() tell you the current state of your socket. Not the same thing.
isConnected() tells you whether you have connected this socket. You have, so it returns true.
isClosed() tells you whether you have closed this socket. Until you have, it returns false.
If the peer has closed the connection in an orderly way
read() returns -1
readLine() returns null
readXXX() throws EOFException for any other XXX.
A write will throw an IOException: 'connection reset by peer', eventually, subject to buffering delays.
If the connection has dropped for any other reason, a write will throw an IOException, eventually, as above, and a read may do the same thing.
If the peer is still connected but not using the connection, a read timeout can be used.
Contrary to what you may read elsewhere, ClosedChannelException doesn't tell you this. [Neither does SocketException: socket closed.] It only tells you that you closed the channel, and then continued to use it. In other words, a programming error on your part. It does not indicate a closed connection.
As a result of some experiments with Java 7 on Windows XP it also appears that if:
you're selecting on OP_READ
select() returns a value of greater than zero
the associated SelectionKey is already invalid (key.isValid() == false)
it means the peer has reset the connection. However this may be peculiar to either the JRE version or platform.
It is general practice in various messaging protocols to keep heartbeating each other (keep sending ping packets) the packet does not need to be very large. The probing mechanism will allow you to detect the disconnected client even before TCP figures it out in general (TCP timeout is far higher) Send a probe and wait for say 5 seconds for a reply, if you do not see reply for say 2-3 subsequent probes, your player is disconnected.
Also, related question
I see the other answer just posted, but I think you are interactive with clients playing your game, so I may pose another approach (while BufferedReader is definitely valid in some cases).
If you wanted to... you could delegate the "registration" responsibility to the client. I.e. you would have a collection of connected users with a timestamp on the last message received from each... if a client times out, you would force a re-registration of the client, but that leads to the quote and idea below.
I have read that to actually determine whether or not a socket has
been closed data must be written to the output stream and an exception
must be caught. This seems like a really unclean way to handle this
situation.
If your Java code did not close/disconnect the Socket, then how else would you be notified that the remote host closed your connection? Ultimately, your try/catch is doing roughly the same thing that a poller listening for events on the ACTUAL socket would be doing. Consider the following:
your local system could close your socket without notifying you... that is just the implementation of Socket (i.e. it doesn't poll the hardware/driver/firmware/whatever for state change).
new Socket(Proxy p)... there are multiple parties (6 endpoints really) that could be closing the connection on you...
I think one of the features of the abstracted languages is that you are abstracted from the minutia. Think of the using keyword in C# (try/finally) for SqlConnection s or whatever... it's just the cost of doing business... I think that try/catch/finally is the accepted and necesary pattern for Socket use.
I faced similar problem. In my case client must send data periodically. I hope you have same requirement. Then I set SO_TIMEOUT socket.setSoTimeout(1000 * 60 * 5); which is throw java.net.SocketTimeoutException when specified time is expired. Then I can detect dead client easily.
I think this is nature of tcp connections, in that standards it takes about 6 minutes of silence in transmission before we conclude that out connection is gone!
So I don`t think you can find an exact solution for this problem. Maybe the better way is to write some handy code to guess when server should suppose a user connection is closed.
As #user207421 say there is no way to know the current state of the connection because of the TCP/IP Protocol Architecture Model. So the server has to notice you before closing the connection or you check it by yourself.
This is a simple example that shows how to know the socket is closed by the server:
sockAdr = new InetSocketAddress(SERVER_HOSTNAME, SERVER_PORT);
socket = new Socket();
timeout = 5000;
socket.connect(sockAdr, timeout);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream());
while ((data = reader.readLine())!=null)
log.e(TAG, "received -> " + data);
log.e(TAG, "Socket closed !");
Here you are another general solution for any data type.
int offset = 0;
byte[] buffer = new byte[8192];
try {
do {
int b = inputStream.read();
if (b == -1)
break;
buffer[offset++] = (byte) b;
//check offset with buffer length and reallocate array if needed
} while (inputStream.available() > 0);
} catch (SocketException e) {
//connection was lost
}
//process buffer
Thats how I handle it
while(true) {
if((receiveMessage = receiveRead.readLine()) != null ) {
System.out.println("first message same :"+receiveMessage);
System.out.println(receiveMessage);
}
else if(receiveRead.readLine()==null)
{
System.out.println("Client has disconected: "+sock.isClosed());
System.exit(1);
} }
if the result.code == null
On Linux when write()ing into a socket which the other side, unknown to you, closed will provoke a SIGPIPE signal/exception however you want to call it. However if you don't want to be caught out by the SIGPIPE you can use send() with the flag MSG_NOSIGNAL. The send() call will return with -1 and in this case you can check errno which will tell you that you tried to write a broken pipe (in this case a socket) with the value EPIPE which according to errno.h is equivalent to 32. As a reaction to the EPIPE you could double back and try to reopen the socket and try to send your information again.
This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 7 years ago.
I am developing a Chat system,where i wanted to keep a list of active clients.
So inorder to make sure that the client is active , i will check whether the client is active in that particular port or not.
In order to test client Activity, I considered the following:
getInputStream.read(): I have n number of clients, so I dont want to keep threads active waiting for return statement -1.
isConnected() command is always returning true.
out.checkError() will throw Exception, I dont wish to throw any Exception and get interrupted.
So I have my logic to establish connection through that port and create a file in that client machine. But i am not sure how to do it.
getInputStream.read() - I have n number of clients, so i dont want to keep threads active waiting for return statement
You should use N threads, one per client, like everybody else does. And a socket read timeout.
isConnected() command is always returning true.
It's not a command, it's a method, otherwise correct. It tells you about the state of the Socket, not of the connection. It becomes true once you've connected or accepted the Socket: it never becomes false.
out.checkError() will throw Exception
No it won't. It will return a boolean if there was an IOException writing to the PrintWriter or PrintStream, but it won't tell you what the exception was, and it doesn't apply to read exceptions, so it isn't all that much use. In fact you shouldn't use PrintWriter at all over a network for that reason, you should use BufferedWriter.
Use a thread per client.
I don't wish to throw any Exception
Bad luck, that's the only way you're going to detect a connection abort.
and get interrupted.
I don't know what this means.
I'm currently working with sockets in Java.
I have created a listener which will connect to a ServerSocket. This works perfectly fine. However, if my application may encounter unexpected closure, the sockets won't be closed properly. Upon the next run, this will throw a SocketException: socket closed on socket = serversocket.accept();
However, by testing with serversocket.isBound() I've discovered that the serversocket is in fact bound and therefor not closed. Is there any way for me to determine whether it is possible for me to accept the connection and if not, to clear the socket and accept after this?
Thanks in advance.
However, if my application may encounter unexpected closure, the sockets won't be closed properly. Upon the next run, this will throw a SocketException: socket closed on socket = serversocket.accept();
You have that back to front. 'Socket closed' means the socket was closed, not that it wasn't.
However, by testing with serversocket.isBound() I've discovered that the serversocket is in fact bound and therefor not closed.
Wrong. isBound() tells you whether you ever called bind(), explicitly or implicitly. It doesn't change what it returns after you close the socket. Try isOpen() or isClosed(), whichever it is, if you want to know whether the socket is still open.
You need to believe what the exception is telling you. You closed the server socket so now you can't accept from it.
Is there any way for me to determine whether it is possible for me to accept the connection and if not, to clear the socket and accept after this?
It would be more to the point to fix the bug whereby the socket ever got closed in the first place.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Does close ever throw an IOException?
Can someone explain to me why socket.close() throws an IOException in Java? I seriously can not figure out how closing a socket is any different from telling the runtime to go right ahead and clean up the resources that the socket is holding onto. Is there another way of not leaking memory and cleaning up socket resources that I don't know of?
It turns out that in many cases the only time that an extant error can be communicated to the calling code is when close() is called. For example, if you have sent a UDP packet that has been rejected by the receiving computer, the only chance you have to find out about it is the next time you use that socket. If the next time you use that socket is to close it, that's when you get the exception. Note that the exception does not prevent the socket from closing, which seems to be what you're asking.
One case ... a socket that has not been opened.
This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 1 year ago.
Hey all. I have a server written in java using the ServerSocket and Socket classes.
I want to be able to detect and handle disconnects, and then reconnect a new client if necessary.
What is the proper procedure to detect client disconnections, close the socket, and then accept new clients?
Presumably, you're reading from the socket, perhaps using a wrapper over the input stream, such as a BufferedReader. In this case, you can detect the end-of-stream when the corresponding read operation returns -1 (for raw read() calls), or null (for readLine() calls).
Certain operations will cause a SocketException when performed on a closed socket, which you will also need to deal with appropriately.
The only safe way to detect the other end has gone is to send heartbeats periodically and have the other end to timeout based on a lack of a heartbeat.
Is it just me, or has nobody noticed that the JavaDoc states a method under ServerSocket api, which allows us to obtain a boolean based on the closed state of the serversocket?
you can just loop every few seconds to check the state of it:
if(!serverSocket.isClosed()){
// whatever you want to do if the serverSocket is connected
}else{
// treat a disconnected serverSocket
}
EDIT: Just reading your question again, it seems that you require the server to just continually search for connections and if the client disconnects, it should be able to re-detect when the client attempts to re-connect. should'nt that just be your solution in the first place?
Have a server that is listening, once it picks up a client connection, it should pass it to a worker thread object and launch it to operate asynchronously. Then the server can just loop back to listening for new connections. If the client disconnects, the launched thread should die and when it reconnects, a new thread is launched again to handle the new connection.
Jenkov provides a great example of this implementation.