Java 关闭BufferedReader/PrintWriter是否会关闭套接字连接?

Java 关闭BufferedReader/PrintWriter是否会关闭套接字连接?,java,sockets,Java,Sockets,我有一个应用程序,它使用简单的套接字在两个系统之间传递一些字符。我的java应用程序作为服务器运行。我建立了良好的连接,甚至传递了一条消息。但是,在发送一条消息后,我的连接关闭 据我所知,在关闭printWriter和bufferedReader时,套接字本身似乎正在关闭?!这很糟糕,因为我在同一个连接上要发送多条消息 printWriter = new PrintWriter(theServer.getClientSocket().getOutputStream()); bufferedRea

我有一个应用程序,它使用简单的套接字在两个系统之间传递一些字符。我的java应用程序作为服务器运行。我建立了良好的连接,甚至传递了一条消息。但是,在发送一条消息后,我的连接关闭

据我所知,在关闭
printWriter
bufferedReader
时,套接字本身似乎正在关闭?!这很糟糕,因为我在同一个连接上要发送多条消息

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?

我满脑子都是吗?如何在Java中维护此连接

是的,关闭任何编写器/读取器都将关闭它们包装的所有其他编写器和读取器。在准备好关闭基础套接字之前不要关闭它。

作为@Eddie(在我前面几秒!:),关闭编写器和/或读取器将关闭基础套接字流:但是,我相信套接字本身不会关闭

关闭返回的InputStream将关闭关联的套接字


你不应该关闭作者或读者。只需刷新书写器,以确保您的消息将及时到达。稍后关闭套接字将关闭相应的流,因此您无需自己关闭它们。只需将您的读写器对象留给GC即可。

关闭流后,您需要关闭套接字。

另一种选择是创建自己的NoCloseInputStream和NoCloseOutputStream筛选器,它们在关闭时不做任何操作;然后使用它们包装应用程序套接字的流(在像缓冲区一样包装任何应用程序之前)

请注意,如果要执行此操作,则需要保留对套接字(或包装流)的引用,以便在实际使用套接字时关闭它


要回答“这对于OP来说太高级了”的评论:OP的问题是,在关闭顶级流时,他也关闭了底层套接字,但这是不好的,因为他想在套接字上创建更多的顶级流来发送更多的消息。根据他的体系结构,实现这一点的唯一方法可能是将流包装在NoClose包装器中-例如,他可能将流传递给XML序列化程序或反序列化程序,该程序在完成时关闭流,而关闭不在他的控制范围内。

我需要刷新缓冲区吗?我可以不使用这些行,继续按照上面的代码使用套接字吗?如果要控制这些行何时到达导线,则需要刷新。Close是隐式刷新。如果您想在调用close之前刷新,请务必调用flush。请注意,在使用读写器时,如果您要使用一个持续打开的套接字来来回传输数据,我会在创建读写器对象后保存对它们的本地引用。我每次都在创建它们,但引用的是同一个套接字,内存泄漏很大。更新为仅在套接字更改时创建并重用对象,泄漏消失。我发现这篇文章是因为内存泄漏,这有助于解决它。我相信这个答案对于这个问题来说太高级了。在我看来,这只会混淆OP。@SoftwareMank不使用NoCloseInputStream做一些事情,为什么不简单地刷新流并让它保持打开状态,直到需要关闭底层套接字时?@Pacerier:因为,正如我所说的和其他一些事情一样,一些设计糟糕的库,比如Java内置的XML实现,无条件关闭任何给定的流。您可能还需要几层包装,并且能够关闭所有这些包装,直到基本套接字继续使用套接字而不是包装。正如我所说,“另一种选择是…”关闭流不也会关闭套接字吗?根据Oracle的说法不是这样的:IMO SoftwareMank有最好的答案@HendyIrawan谢谢你的更正。你是对的;从Java 6开始就有文档记录: