Closing a socket when a thread dies - java

I'm having problem closing a socket when the Java program is terminated (By exception or manually). I could use some help!
I'm writing a program in Java that uses TCP socket to communicate with a server.
I have a socket that is used by two threads - one uses it for sending data and the other one for receiving data. My current idea to deal with the problem is closing the socket while the receiving data thread dies (i would love to hear more ideas). I didn't find any way to close the socket when the thread (the whole program) is terminated. Is there any way to call the close method when the thread is dying? (Looking for something kind of like C++'s destructor)
Iv'e tried using statement and try-finally and it didn't work.
public class Receive implements Runnable {
....
....
public void run() {
Socket socket = getSocket() // Gets socket from a singleton class.
....
while (true){
....
readFromSocketFunction();
....
}
....
} // Would like to close the socket when going out from this scope.
....
}
Right now when I terminate the program, the socket keeps living. I wrote a simple client in Python and I noticed that when i interrupt the client while running, it still closes the socket (the server disconnects from the client), and I would like to have the same behavior in my program.
Thanks!!

Related

Does my Java socket stay open when using it in a thread?

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.

program freezes when listening for client through sockets

I'm trying to make a server socket to listen to a client input stream but when i execute the start_listening() method, my program gets stuck. I even tried to remove the loop, but i still have the same problem. i guess that it waits for the client interaction. is there an alternative way to listen while the program is also working?
public static void start_listening(){
listener = new ServerSocket(9090);
while (true) {
Socket socket = listener.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
us = (User) in.readObject();
}
}
When using the sockets technique, accept() blocks the execution of the current thread until a client connects to the listening socket. This is a defined behavior. Java documentation says: "The method [accept()] blocks until a connection is made." Have the server run within a endless loop can be ok.
So, to get this whole thing run you might want to take a look at this socket example which uses threads. Inside the run() method of ConnectionHandler you would deal with your User object.
Besides that the loop never ends (I suppose you will break at some point), you should do that kind of stuff in a separate Thread or an AsyncTask, doing accept in the main thread makes Andriod freeze until somebody connects to the socket. That's why your program gets stuck.
You might just use a Boolean flag to indicate when to end the while loop.Other wise the loop keep iteration as it never breaks.
while (true) { //will it ever breaks ??
}

Java - readObject() and setSoTimeout()

So, i wrote a thread on my client side , which tries to readObject() from a socket stream.
This thread runs as long the client is connected.
The connection to the server can be closed on the client's GUI.
If the client decides to disconnect(this will not exit the client program) by clicking the
"disconnect" menu option, the socket will be closed and a isConnected is set to false.
Since the clients read thread tries to readObject() from stream, while the connection can be closed via the GUI, i set a timeout to 250ms (setSoTimeout(250)).
#Override
public void run()
{
this.connection = this.connectionHandler.getSocket();
while(connectionHandler.isConnected())
{
this.readCircle();
}
this.connectionHandler.setReadTaskRunning(false);
}
private void readCircle()
{
try
{
this.connection.setSoTimeout(250);
this.connectionHandler.readData(); //this uses readObject().
}
catch(SocketTimeoutException timeout){}
catch(...){}
}
I know that readObject() will block, and to check if the client is still connected, i wraped it in a while, which checks (every timeout) if the client socket is still connected.
My question now:
In case, if the readObject() starts to get a object passed by the server, tries to read it, but while processing a timeout occurs, will the data on the stream be "damaged" in some way, because it canceled.
Or should i just let the readObject() block and catch a exception if the GUI thread wants to close the socket.
I'm not very experienced with sockets and maybe my approach is wrong at all.
Socket read timeout will cause a SocketTimeoutException to be thrown by readObject(). You may not be able to reuse that ObjectInputStream, and the stream may be damaged because its current position will stay largely undefined.
This probably can only be fixed by closing and reopening the connection.

Identify lost Socket connection without opening its IO stream

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.

Java: nice way to stop threaded TCP server?

I have the following structure for TCP client-server communication:
On server startup server starts
acceptor thread, that accepts client
connections and passes ServerSocket
to it.
When a client connection arrives,
acceptor thread calls accept() on
ServerSocket and submits client
processing job to worker thread
(by executor/thread pool) and provides client socket to it.
Worker in loop reads data from
client socket stream, processes it and sends replies.
The question is how to gracefully stop the whole system? I can stop acceptor thread by just closing ServerSocket. It will cause accept() blocking call to throw SocketException. But how to stop workers? They read from stream and this call is blocking. According to this streams does not throw InterruptedException and thus worker cannot be interrupt()'ed.
It looks like I need to close worker socket from another thread, right? For this, socket should be made a public field or a method should be provided in worker to close it. Will this be nice? Or may be my whole design is flawed?
Your model works appropriately. The best way of interrupting non-interruptable constructs like IO is to close the socket. You can of course handle it before you go into a blocking state, but if the IO functions don't react to interruption you dont really have many good options
I would suggest using a boolean flag that the workers check periodically. Call the flag shouldStop and if it's set to true, the worker cleans up and then dies. Following this method would allow you to implement some clean-up code so you don't leave resources hanging, etc.
You must not simply stop the server. The shutdown process might take a while while cleanup occurs because you need to ensure consistency.
Imagine a database server, if you simply shut it down while it is carrying out transactions you may leave its data inconsistent. That's why it typically takes a while to shutdown the server.
You must first stop accepting new
connections in the server.
Then you can either wait for the
current worker threads to finish
their work and then close the
server and shutdown officially.
Or you force the worker threads to
close their connections with the
client (probably using some sort
of flag as suggested). This might
imply some cleanup to leave data
consistent, for instance revert
trasnsactions or any kind of changes
you have done in files or in memory.
Closing the connections with the clients in the server side should cause the clients to get a EOF on their sides as far as I understand.
[EDIT-1]
I have delved a bit on the issue, just because I had not used sockets in a while and because I found the question interesting. I think as it has been well pointed out by others, the only option is to close the socket, which according got Javadocs will automatically close the input and output streams/
If there are chances that the thread is not IO-blocked, but in wait state or sleeping, I think it is still recommended to issue a Thread.interrupt() for the corresponding worker thread of a given socket; because there cannot be certainty of the blocking of state of every thread.
public static class IOServerWorker implements Runnable{
private Socket socket;
public IOServerWorker(Socket socket){
this.socket = socket;
}
#Override
public void run() {
String line = null;
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while( (line = reader.readLine())!=null){
System.out.println(line);
}
reader.close();
}catch(IOException e){
//TODO: do cleanup here
//TODO: log | wrap | rethrow exception
}
}
}

Resources