简体   繁体   English

如何在保持输入流打开的同时关闭 Java 套接字的输出流以获得结果?

[英]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 .但是,在尝试读取结果时,我收到了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)

From the javadoc of Socket.getOutputStream() :来自Socket.getOutputStream()javadoc

Closing the returned OutputStream will close the associated socket.关闭返回的OutputStream将关闭关联的套接字。

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:您可以使用Socket.shutdownOutput()来防止进一步写入套接字,但我并没有真正看到使用它的意义,并且它可能导致对等方过早关闭其套接字,正如Stephen C在评论中解释的那样:

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.接下来会发生什么取决于它如何响应看到关闭的流。

You can't close an OutputStream without closing the socket(See two links below).您不能在不关闭套接字的情况下关闭 OutputStream(请参阅下面的两个链接)。 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.如果通道处于非阻塞模式,则输出流的写入操作将抛出 IllegalBlockingModeException。

Closing the returned OutputStream will close the associated socket.关闭返回的 OutputStream 将关闭关联的套接字。

Behavior of Java sockets when closing output stream 关闭输出流时 Java 套接字的行为

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

As mentioned by Joseph, I don't think you should close the OutputStream before opening the InputStream.正如约瑟夫提到的,我认为您不应该在打开 InputStream 之前关闭 OutputStream。

According to Oracle Docs ( https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html ), the correct order is:根据 Oracle Docs ( https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html ),正确的顺序是:

  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.关闭插座。

To only close the output stream, use要仅关闭输出流,请使用

socket.shutdownOutput()

See docs查看文档

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.正如@MarkRotteveel 所提到的,您可以通过在发送所有要发送的内容后关闭用于输出的发送套接字来克服它,但这会将您限制为每个连接一个请求/响应。

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.例如,您可能应该发送线路。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM