17

I have an application that uses simple sockets to pass some characters between two systems. I have my java application running as a server. I establish a connection fine, and even pass one message. However, after one message has been sent my connection closes.

From what I can tell it appears as if on closing the printWriter and bufferedReader the socket itself is being closed?! This is bad, as I have multiple messages to send on the same connection.

printWriter = new PrintWriter(theServer.getClientSocket().getOutputStream());
bufferedReader = new BufferedReader(new InputStreamReader(theServer.getClientSocket().getInputStream()));


printWriter.println("the line");

printWriter.close(); //Closing on these lines?
bufferedReader.close(); //Closing on these lines?

Am I full of it? How do I maintain this connection in Java?

palacsint
  • 28,416
  • 10
  • 82
  • 109
Alex
  • 6,843
  • 10
  • 52
  • 71

4 Answers4

19

Yes, closing any Writer/Reader will close all other Writers and Readers that they wrap. Don't close it until you are ready to close the underlying socket.

Eddie
  • 53,828
  • 22
  • 125
  • 145
  • Do I need to flush the buffers then? Can I just leave those lines out and keep using the socket per the code above? – Alex Jan 27 '09 at 19:51
  • 1
    You will need to flush if you want to control when the lines hit the wire. – Darron Jan 27 '09 at 19:54
  • Close is an implicit flush. If you want to flush before you call close, then by all means, call flush. – Eddie Jan 27 '09 at 20:15
  • 1
    Just a note when using Reader/Writers, if you are going to use a constant open socket to transmit data back and forth, I would save a local reference to both your reader and writer objects once they are created. I was creating them every time but referencing the same socket and had a huge memory leak. Updated to only create on socket change and reuse the objects, leak is gone. I found this post due to a memory leak and this helped solve it. – Slopes Sep 15 '15 at 22:40
10

As @Eddie said (seconds before me! :) ), closing the writer and/or the reader will close the underlying socket streams and the socket itself: However, I believe the socket itself will not be closed.

Closing the returned InputStream will close the associated socket.

You shouldn't close the writer nor the reader. Just flush the writer to make sure your messages will arrive in time. Closing the socket later on will close the respective streams, so you don't need to close them yourself. Just leave your reader/writer objects to the GC.

Community
  • 1
  • 1
Hosam Aly
  • 41,555
  • 36
  • 141
  • 182
  • @HendyIrawan Thanks for the correction. You're right; it's been documented since Java 6: http://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#getInputStream() – Hosam Aly Jul 23 '14 at 11:17
5

Another alternative is to create yourself a NoCloseInputStream and NoCloseOutputStream filters which simply do nothing on close; then use them to wrap your application socket's streams (before any application wrappering like a buffer).

Note that if you were to do this, you would need to keep a reference to the socket (or the wrapped streams) so that you can close the socket when you are actually done with it.

To answer the comment that this is "too advanced a concept for the OP": The OP's problem is that in closing the top level stream, he is also closing the underlying socket, but that's no good since he wants to create further top-level streams over the socket to send further messages. Depending on his architecture, the only way to achieve this may be to wrap the streams in NoClose wrappers - for example he may be passing the streams to an XML serializer or deserializer which closes the stream when it's done, which close is outside of his control.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
  • I believe this answer is too advanced for the question. It can only confuse the OP in my opinion. – Hosam Aly Jan 28 '09 at 18:59
  • @SoftwareMonk Instead of doing something with NoCloseInputStream, why not simply flush the stream and leave it open until the time when you need to close the underlying socket? – Pacerier Jul 16 '12 at 18:12
  • @Pacerier: Because, as I said and among other things, some badly designed libraries, such as the XML implementation built into Java, close any stream given them unconditionally. You may also want several layers of wrappering and to be able close all of those up until the base socket to continue to use the socket but not the wrappers. As I said, *"Another alternative is to..."* – Lawrence Dol Jul 19 '12 at 18:07
2

You need to close the socket after closing the streams.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130