AlikElzin-kilaka
AlikElzin-kilaka

Reputation: 36001

How to close a Java's socket's outputstream while keeping the inputstream open to get a result?

I'm sending a message to a server, which passes correctly.

But, when trying to read the result, I get an exception that the Socket is closed.

Any idea how to close the socket's outputstream while keeping the socket and socket's inputstream open to get the result?

Client code:

Socket socket = new Socket("localhost", 9090);
String message = "Some message";
new OutputStreamWriter(socket.getOutputStream(), Charsets.UTF_8)
        .append(message)
        .close();
// The following line throws the exception when socket.getInputStream() is called:
String fromServer = CharStreams.toString(new InputStreamReader(socket.getInputStream(), Charsets.UTF_8));

Exception:

java.net.SocketException: Socket is closed

    at java.net.Socket.getInputStream(Socket.java:903)
    at alik.server.test.Client.pingServer(Client.java:24)

Upvotes: 2

Views: 3828

Answers (5)

dwb
dwb

Reputation: 2624

To only close the output stream, use

socket.shutdownOutput()

See docs

Upvotes: 0

user207421
user207421

Reputation: 310885

You can't. Closing a socket input or output stream closes the other stream and the socket.

However the real problem here is that the peer is trying to read until end of stream before it sends anything back. This is an applicaton protocol issue. You could overcome it by shutting down the sending socket for output after sending everything that is to be sent, as mentioned by @MarkRotteveel, but this restricts you to one request/response per connection.

It would be better to review your application protocol to discover how the peer can know where the end of a request is, and only read that far before replying. For example, possibly you should be sending lines.

Upvotes: -1

Mark Rotteveel
Mark Rotteveel

Reputation: 108982

From the javadoc of Socket.getOutputStream():

Closing the returned OutputStream will close the associated socket.

In other words, don't close the output stream until you are done with the input stream. Closing the input stream will also close the socket (and as a result, also the output stream).

You could use Socket.shutdownOutput() to prevent further writing to the socket, but I don't really see the point of using that, and it could result in the peer closing its socket prematurely, as Stephen C explains in the comments:

The peer should only see the closed stream if it reads. What happens next will depend on how it responds to seeing the closed stream.

Upvotes: 11

Ultcyber
Ultcyber

Reputation: 406

As mentioned by Joseph, I don't think you should close the OutputStream before opening the InputStream.

According to Oracle Docs (https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html), the correct order is:

  1. Open a socket.
  2. Open an input stream and output stream to the socket.
  3. Read from and write to the stream according to the server's protocol.
  4. Close the streams.
  5. Close the socket.

Upvotes: 1

MajikalExplosions
MajikalExplosions

Reputation: 118

You can't close an OutputStream without closing the socket(See two links below). Is there a specific reason why you need to do this?

You would need to finish read/writing before you close the socket and it's input/output streams.

Returns an output stream for this socket.

If this socket has an associated channel then the resulting output stream delegates all of its operations to the channel. If the channel is in non-blocking mode then the output stream's write operations will throw an IllegalBlockingModeException.

Closing the returned OutputStream will close the associated socket.

Behavior of Java sockets when closing output stream

https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#getOutputStream()

Upvotes: 2

Related Questions