Java 创建一个新的 ObjectInputStream 块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5658089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Creating a new ObjectInputStream Blocks
提问by ericso
I'm trying to create a new ObjectInputStream using an InputStream retrieved from a Socket. Here is my code:
我正在尝试使用从套接字检索的 InputStream 创建一个新的 ObjectInputStream。这是我的代码:
This is the constructor for my MessageGetterSender class. The program does not get to Checkpoint 4.
这是我的 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");
}
I'm instantiating a new MessageGetterSender object from a class in which I connect to a server to get the socket. Here is the relevant code. It is the constructor for the InstantMessageClass, the class that instantiates the MessageGetterSender object:
我正在从一个类中实例化一个新的 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);
...
Since the code does not execute to Checkpoint 4 but it does get to Checkpoint 3, I'm pretty sure the instantiation of the ObjectInputStream is the culprit. I cannot figure out why though. Any ideas? Thanks for the help.
由于代码不会执行到检查点 4 但它确实到达了检查点 3,我很确定 ObjectInputStream 的实例化是罪魁祸首。我不明白为什么。有任何想法吗?谢谢您的帮助。
回答by Haywood Slap
Just to expand on FatGuy's answer for other Googlers that find this; the solution to this "chicken and egg problem" is to have each side open the output stream first, flush the output stream, and then open the input stream.
只是为了扩展 FatGuy 对其他发现此问题的 Google 员工的回答;这个“鸡和蛋问题”的解决方案是让每一方先打开输出流,刷新输出流,然后再打开输入流。
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
回答by MeBigFatGuy
When you construct an ObjectInputStream
, in the constructor the class attempts to read a header that the associated ObjectOutputStream
on the other end of the connection has written. It will not return until that header has been read. So if you are seeing the constructor 'hang', it's because the other side of the socket either hasn't used an ObjectOutputStream
, or hasn't flushed the data yet.
当您构造 时ObjectInputStream
,在构造函数中,该类会尝试读取ObjectOutputStream
连接另一端的关联对象已写入的标头。在读取该标头之前它不会返回。因此,如果您看到构造函数“挂起”,那是因为套接字的另一端没有使用ObjectOutputStream
,或者尚未刷新数据。
回答by Mihai Danila
You can also delay the initialization of the ObjectInputStream until data is available in the underlying stream.
您还可以延迟 ObjectInputStream 的初始化,直到基础流中的数据可用。
This approach works regardless of the stream initialization order, and is especially useful if one end of the channel is in library code that you cannot change.
无论流初始化顺序如何,这种方法都有效,并且在通道的一端位于您无法更改的库代码中时尤其有用。