Java 创建一个新的 ObjectInputStream 块
Posted
技术标签:
【中文标题】Java 创建一个新的 ObjectInputStream 块【英文标题】:Java Creating a new ObjectInputStream Blocks 【发布时间】:2011-08-05 05:04:22 【问题描述】:我正在尝试使用从 Socket 检索的 InputStream 创建一个新的 ObjectInputStream。这是我的代码:
这是我的 MessageGetterSender 类的构造函数。程序无法到达检查点 4。
public MessageGetterSender(Socket socket)
System.out.println("MessageGetterSender: Checkpoint 1");
this.socket = socket;
// Get input and output streams
try
System.out.println("MessageGetterSender: Checkpoint 2");
InputStream is = socket.getInputStream();
System.out.println("MessageGetterSender: Checkpoint 3");
this.in = new ObjectInputStream(is);
System.out.println("MessageGetterSender: Checkpoint 4");
catch (IOException ioe)
System.out.println("Could not get ObjectInputStream on socket: " + socket.getLocalPort());
try
this.out = new ObjectOutputStream(socket.getOutputStream());
catch (IOException ioe)
System.out.println("Could not get ObjectOutputStream on socket: " + socket.getLocalPort());
System.out.println("MessageGetterSender: Checkpoint 5");
我正在从一个连接到服务器以获取套接字的类中实例化一个新的 MessageGetterSender 对象。这是相关的代码。它是 InstantMessageClass 的构造函数,该类实例化 MessageGetterSender 对象:
public InstantMessageClient(String username)
try
socket = new Socket("localhost", 5555);
catch (IOException ioe)
System.out.println("Error: Could not connect to socket on port: " + serverPort);
messageGetterSender = new MessageGetterSender(socket);
...
由于代码没有执行到检查点 4,但它确实到达了检查点 3,我很确定 ObjectInputStream 的实例化是罪魁祸首。我不知道为什么。有任何想法吗?感谢您的帮助。
【问题讨论】:
【参考方案1】:当您构造ObjectInputStream
时,该类在构造函数中尝试读取连接另一端的关联ObjectOutputStream
已写入的标头。在读取该标头之前它不会返回。因此,如果您看到构造函数“挂起”,那是因为套接字的另一端没有使用ObjectOutputStream
,或者还没有刷新数据。
【讨论】:
【参考方案2】:只是为了扩展 FatGuy 对其他发现此问题的 Google 员工的回答;解决这个“鸡和蛋问题”的方法是让每一方先打开输出流,刷新输出流,然后再打开输入流。
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
【讨论】:
这确实是正确的解决方案。你把它描述为“鸡和蛋”的问题,一针见血。 我想说out.flush()
不是必需的(除非您使用一些缓冲流作为底层流),因为ObjectOutputStream
使用的BlockDataOutputStream
在启用块数据之前写入流标头模式。【参考方案3】:
您还可以延迟 ObjectInputStream 的初始化,直到底层流中的数据可用。
无论流初始化顺序如何,这种方法都有效,如果通道的一端位于您无法更改的库代码中,则特别有用。
【讨论】:
我能问一下如何去做吗? 我认为您可以查看底层流以查看是否有可用数据。我已经有一段时间没有查看 Stream API 了。以上是关于Java 创建一个新的 ObjectInputStream 块的主要内容,如果未能解决你的问题,请参考以下文章