Java套接字在关闭输出流时的行为

24

有人能解释一下Java sockets中以下行为吗:

大概的想法是这样的:

  1. 打开socket,获取I/O流。
  2. 写请求,关闭输出流
  3. 读取响应,关闭输入流
  4. 关闭socket。

这是我的问题/问题所在:

如果我使用PrintWriter进行输出,然后关闭它,它会关闭整个socket,随后的读操作失败得很惨。

相反,如果我直接使用socket的shutdownOutput()方法,它将正确关闭输出流通道,同时保持socket处于活动状态。

为什么关闭PrintWriter对象会导致整个socket关闭?


1
在关闭之前,你可能需要刷新它。 - Bhesh Gurung
1
在关闭PrintWriter之前,您尝试过使用.flush()刷新连接并查看问题是否仍存在吗? - vcetinick
@vcetinick 那没有关系。close() 调用了 flush() - user207421
2个回答

34

你的代码可能长成这样:

Socket socket;
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.close();

现在,让我们来看一下Socket类中getOutputStream()方法的描述.

getOutputStream

public OutputStream getOutputStream() throws IOException

返回此套接字的输出流。如果此套接字具有关联通道,则生成的输出流将委托其所有操作给该通道。如果通道处于非阻塞模式,则输出流的写入操作将引发IllegalBlockingModeException异常。

关闭返回的OutputStream将关闭关联的套接字。

返回:

用于向此套接字写入字节的输出流。

抛出:

IOException - 如果创建输出流时发生I/O错误或套接字未连接。

从上面的描述中,我们知道关闭返回的OutputStream将关闭关联的套接字。

当您关闭PrintWriter时,它将关闭关联的OutputStream,进而关闭关联套接字。


4
RTFM 哦? :) 我想这样解释得很透彻了。谢谢 Bloodwolf! (翻译:RTFM是英文“Read the F***ing Manual”的缩写,意思是“去读他妈的手册”,常用来表示某人提问之前没有阅读相关说明文档或手册。原话中的“Thanks Bloodwolf!”则表示感谢对方提供解释或帮助) - Lenny Markus
1
@Alanmars 如何避免这种情况。如果我想在关闭OutputStream后仍保持套接字打开,有没有办法做到这一点? - vishal munde
1
我仍然不明白“为什么”。 “为什么关闭PrintWriter对象会将整个套接字一起关闭?” - AlikElzin-kilaka

3
可能是因为调用PrintWriterclose()方法会顺着层次结构返回并调用SocketOutputStreamclose()方法。在SocketOutputStreamclose()方法中,它也会调用Socketclose()方法,从而关闭SocketInputStream。相反,调用shutdownOutput()函数会发送先前写入的任何数据,然后按照TCP的正常连接终止序列进行。然后禁用输出流。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接