I'm writing a simple Java server that accepts multiple client socket connections. I'm using a separate thread to handle each client/socket. Considering I have set up the networking including the BufferedReader, InputStreamReader, and FileWriter etc. for this client/socket.
My code is :
//run method of my Runnable everytime a new client connects
public void run(){
String message = null;
while((message = bufferedReader.readLine())!=null){
System.out.println(message+"/n");
//do some other things like writing this message
//to another client or saving it in a file, etc
}
}
Does this keep the client socket open? or does the socket eventually makes the thread goes dead when it's done reading from the stream
Will it keep waiting for more/new messages/data from the client socket even after it's done reading for the first time?
Once the server accept client request, the server is capable of exchanging messages with the client endlessly until the socket is closed with its streams.
To allow continuity in communication, you have to read from the stream inside a while loop and only exit when the client sends a termination request. So in your case the client socket is open until you read, once you exit from the loop your connection will be terminated.
Where did you create the bufferedReader ?
The thread will end when the readLine call returns null. That happens when the reader reaches the "end of stream". If the BufferedReader is wrapping an input stream associated with a socket, then "end of stream" will be triggered by the socket connection closing; e.g. because the remote client / server closed it.
There is no code shown here to close the BufferedReader. It will be closed if either something else calls close on it, or if the BufferedReader object becomes unreachable. In the latter case, the reader and the underlying socket stream and socket will eventually be closed when the GC finalizes the objects.
My question is does this keep the client socket open? Or does the socket and eventually the thread goes dead when it's done reading from the stream, or will it keep waiting for more/new messages/data from the client socket even after it's done reading for the first time?
It depends. See above.
The point is that the code as written reads until there is no more to read. Not until "it is done". Or to put it another way "it is done" ... if and only if the other end tells it so, by closing the stream.
Related
I am in the process of developing a game and I have a question.
I have a client where a user can log in to the game or disconnect using a unique account stored on a database.
How do I properly close a server on log out and re open on log in? Or should I never close the socket? The same question goes for DataInputStream and DataOutputStream.
I keep getting connection reset client sided, so I don't know what the best way to handle logging in/logging out within the same client runtime.
Thanks. :)
Just close the socket. That will terminate the corresponding thread at the server. One login should equal one socket.
You should do that by closing the outermost stream or Writer wrapped around the socket output stream. That flushes it and closes the other streams and the socket. Closing the input stream and the socket before this is incorrect, and doing so afterwards is redundant, but if you must do it it must be done after, not before, otherwise again you miss a flush.
My SocketServer first listens for at least 4 Socket connections before creating a WorkerThread where all four connections are served. And in the same thread, all 4 sockets will be opened to perform communication with connected clients.
Now, consider a situation where server has already accepted two socket connections, but listening to remaining 2 clients, before it can proceed with creating thread.
And while that listening phase, the connected clients are shown "Waiting..." message (since server has not yet opened the sockets to send any response back to clients, and socket.readObject() is blocking at client-end), till the server gets all 4 clients to work with. And in the meantime, one of the "already-connected" client kills that "Waiting..." thing, and closes the client app. In such a case, my WorkerThread will fire an exception due to dead socket supplied, when it attempts to open it.
How can I know if a socket is pointing to nothing (since client is lost) without having to open the socket? (since if I open it from main thread, I'll not be able to open it again from WorkerThread, where it is actually supposed to be used).
If I get to know if Socket is dead, I can get server back to listening and attempt to get 4 connections, before it proceeds creating a thread.
I know my SocketServer will be stuck at accept() so even if its possible to check what I asked above, I'll have to create another thread that monitors liveliness of already "accepted" socket connections.
Update
I mean by not opening the socket is something like below.
Socket s = ss.accept();
/* I'll not be doing as below, since once I close InputStream and OutputStream in main Thread, I can't open in WorkerThread.
But I still want to know if Socket s is connected to client, before I start WorkerThread.
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
String msg = in.readObject().toString();
System.out.println("Client Says:");
out.writeObject("success");
in.close();
out.close();
*/
new WorkerThread(s).start();
And note that my server is accepting 4 such connections, and when 4 sockets are accept()ed, it passes all 4 in WorkerThread's constructor, and gets back to accept() another 4 clients.
I think you just need to handle your acceptions better. You should handle the IOException correctly whenever you try to read or write to the socket.
One option is to have the accepting code send a "still waiting" message to the client and get an acknowledge every so often while you are waiting for the other connections. The socket and associated streams have already been created by the accept() so you can do this, call flush() on the OutputStream, and then hand off to the handler.
As long as you don't call close() on the streams, you should be able to re-use them without a problem. You just can't have two different threads using the streams at the same time.
I have a thread for each connection on the server-side. When the client is not sending commands, the server thread is blocking:
while ((commandHeader = fromNode.readLine()) != null) {
which internally calls readLine() on an OutputStream obtained from the TCP socket.
When I call socket.close() from another thread, this calls wakes up with a SocketException and the thread can be terminated.
However, if a client than wakes up and decide to issue a command, it executes
stream.writeBytes("something\n");
which blocks indefinitely. I understand this is probably fine for TCP (it's just an half-close.)
I should probably send something to the client upon quitting, like "QUIT\n"; it could also just read an EOF. But if I call readLine() or other read operations on the client before sending the command, they block waiting for data when the connection is not closed.
How can the client detect that the connection has been half-closed before trying to write to it?
When socket.close() is called on server the underlying TCP connection is closed with the typical FIN/FIN-ACK sequence plus RST packets, so the client will know. When the client calls stream.writeBytes() afterwards it should fail. If it doesn't it means there has been some missing packets and the connection eventually will fail anyhow.
First i think your application logic should be such that to avoid Half Open TCP connection. You can think of adding timer on client side so that if nothing received it starts polling the server again.
From server point of view, another option is to set timer on the readLine. Make another method for readLine where you set a timer and if it excedes certain time, simply return some default value to the while loop.
EDIT:
You might want to read this article specially the section: What about threads blocked on IO?
My client/server application currently keeps opening and closing new connections every time it wants to send/receive data. I'm trying to change it so it will have one persistent connection.
The problem I'm having is the socket's DataInputStream on the server keeps throwing EOFException's when I just want it to block until it receives the next batch of data.
I thought about just simply writing the server like this...
while socket is open {
while at socket's DataInputStream's EOF {
wait a second
}
//If we're here, then we have some data
do stuff
}
... but this is extremely ugly and not the proper way to block until some data is received.
Is there a cleaner way to tell the socket to block until there's some data to read? I've tried read() and readFully(), but neither work.
If you are getting EOFException, it means the connection is gone. You cannot wait on a connection that's closed. Keep working on your client code so that it doesn't close the connection. On the server side, any of the read methods will block until data is available without further effort from you.
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.