I have 'n' server threads, and each one listen to 1 client.
When a server thread receives a message from its client, it needs to notify the other 'n-1' clients, and that's the reason why I keep a shared object (containing an array of 'n' sockets, one for each client) between the server threads.
Moreover, in the main server thread that holds the ServerSocket, every time I accept a new connection with a client I open a BufferedWriter/Reader to give a first answer to him using the new socket returned from ServerSocket.accept().
In case of an "OK" answer I open a new thread passing the new socket to it, in order to listen to the new client's following requests.
The problem is that i cannot close the BufferedReader and the BufferedWriter in the main server thread, because it will also close the underlying stream, causing problems to the server thread that is listening to that socket/stream.
And the question: if I open another BufferedReader (bound to the same socket) in the new thread, and then close it, will other BufferedReaders(Writers) ( specifically the ones opened in the main server thread, that i couldn't close before ) opened on the same socket be closed? Will an exception be thrown on them?
It could be possible to share the opened BufferedReader / Writer instead of the socket, to avoid instantiating every time a new object, but this is a question related to what could happen if i do things in the way described above.
Please tell me if I hadn't been clear, my english is not really good.
Closing any Reader or Writer or stream wrapped around a stream closes the wrapped stream.
Closing either the input stream or the output stream of a socket closes the other stream and the socket.
Closing the socket closes both streams.
In other words closing any of it closes all of it.
As noted in comments, multiple buffered streams/Readers/Writers wrapped around a single stream cannot work.
Multiple threads reading from/writing to the same socket is unlikely to work correctly either, unless you take great care with synchronization and buffering.
You should not do any I/O with an accepted socket in the accept loop. Otherwise you can block, which affects further clients.
You need to rethink your design.
Each Socket with an open connection to another Socket has an open InputStream and an open OutputStream. Closing either one of these streams will also close the socket. Closing a socket or its streams will not affect other sockets unless they are connected. You don't want to close any streams unless you also want to close the connection between the sockets using the streams. Please ask if there is something i missed or if you have other questions :)
Related
In a TCP connection between sockets. What is the correct procedure to closing/shutting down the connection?
I have outputstreams, bufferedreaders and printwriters. Will closing the socket close all of them? Should they be closeds at both ends?(server and client)
You should close the outermost stream or writer you have wrapped around the socket output stream. That way it will get flushed if it is buffered.
Closing either the input or output stream or the socket closes everything else.
'Should they be closed at both ends?' doesn't really make sense. Sockets don't have two ends: connections do. The connection must be closed at both ends, but both ends have a socket, and all sockets must be closed.
As the title says - if I want to close a socket connection is it enough if I just call mySocket.close()? What will happen on the other side?
Or, if it's not the way to go, what is? Do I have to send some kind of "finish" message through the socket so the other side knows it should end as well?
Bonus question: java documentations says
Closing this socket will also close the socket's InputStream and OutputStream.
So is closing the socket alone enough or do I have to explicitly close the streams as well (assuming I'm not using try-with-resources, of course)?
Closing the socket won't do any thing on the other side. The remote host will not know that the connection has been closed.
The only way to check whether the connection is closed is to try to read or write from/to the input/output stream. If -1 is returned by the InputStream#read() method, then the second side knows that the first side closed the connection. A thrown IOException also indicates a closed connection.
Normally you don't need to close the in/output stream as they are closed when invoking Socket#close(). Socket#close() is the only thing you need to do to close a connection.
But if you have a wrapper stream (e.g. BufferdInputStream/BufferedOutputStream) you should explicitly close these wrapper streams to release resources used by these wrapper streams (e.g. byte buffer array). You only need to close the top level wrapper stream as closing the wrapper closes the wrapped stream which closes the wrapped stream of the wrapped stream, too. And so on...
socket.close() is a clean way to close the connection. It causes a TCP FIN packet to be sent to the peer and starts the normal TCP shutdown sequence.
It also closes the socket's InputStream and OutputStream, I don't see any ambiguity in the documentation on that point.
I recently noticed in my multi threaded Java socket handler that I was getting exceptions when I tried to write on a socket, however I was still receiving data via reads. It was my understanding that if the socket was closed the input stream reader would also throw a socket closed exception when attempting the next read. Is this not the case and should I manually close the socket if I get this exception when attempting to write?
A TCP connection can be closed in the write direction but not in the read direction, such a connection is called "half closed". You should keep reading the rest of the data the other side sent, otherwise the connection will not close normally.
If you think about it, how else could you sanely shut down a TCP connection? If you shut it all the way down in one step, what happens if the other side sends some data to you before you finish shutting it down? You still need to receive it. But, obviously, you can't keep sending data.
I am working in a legacy java application, In many files, socket and streams are used, where sockets are getting closed but not the streams, is this necessary to close all the streams before closing the socket. because I am getting "too many open files error", is this error because of not closing the streams.....
closing the socket will automatically close the streams also?
From the Socket Javadoc:
Closing this socket will also close the socket's InputStream and OutputStream.
So generally speaking, closing the socket should be enough to close both streams it created.
Your "too many open files error" is most likely caused by something else.
Closing any one of those closes the other two, but you should close the outermost output stream (or Writer) that you have wrapped around the socket. That closes the input stream and the socket. If you don't close the outermost output stream yourself, it won't get flushed, and so you can lose data if there is a buffered outpput stream or writer in the stack. You could also close the socket itself in a finally block to be sure: in fact lack of finally blocks may well be the cause of your problem.
I create a chatting program. My server has a button , the button is for starting the server call accept() method on server socket , button for closing the server call close() on server socket.
When I re-press start button to re-accept connection on the same socket , accept method throws SocketException Socket is closed.
You cannot reopen a socket. If you want to use the variable again, you'll have to create and assign a new socket.
From the Java Documentation on Socket, see info on "close"-method:
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.
If your previous socket was successfully closed, than there should not be problems with re-instantiating that socket. This would work in Java because the JVM will free the garbage for you.
If you want multiple connections to the server (this could be useful since you're making a chat), then keep this in mind.
The accept function, on the server side, will create a new socket every time it's requested. So you can just use threads and pass the new socket (the one created using the accept) to the thread.
If this does not answer your question I would encourage you to go over the Oracle website: http://docs.oracle.com/javase/tutorial/
and to re-formulate the question.