【问题标题】:Must server & client have reverse sequence of claiming ObjectOutputStream & ObjectInputStream?服务器和客户端必须具有声明 ObjectOutputStream 和 ObjectInputStream 的相反顺序吗?
【发布时间】:2013-01-16 08:02:03
【问题描述】:

在我的实验中,

如果服务器有这个:

ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());

然后客户端必须按照相反的顺序执行此操作:

ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());

否则服务器和客户端会死锁。

这是什么原因?是否有正式的 API 规范?

【问题讨论】:

  • 我本以为在写入任何内容之前尝试从InputStream 读取会导致问题(因为读取会阻塞),这意味着如果客户端和服务器都尝试从那里读取各自的@ 987654324@ 在您希望使用写入的同一线程中,然后您会遇到问题...
  • @MadProgrammer 它确实会导致问题。这就是他问的原因。但仅适用于对象流,因为构造分别写入和读取标头。
  • @EJP - 错过了“流”中的“对象”:P - 是时候再喝点咖啡了
  • 回答你标题中的问题,不,只要他们不都尝试先构造ObjectInputStrram。如果他们都尝试先构造ObjectOutoutStrram,这是最安全的。

标签: java sockets serialization objectinputstream objectoutputstream


【解决方案1】:

是的。我知道这怎么可能发生。 ObjectInputStream 构造函数的 javadoc 是这样说的:

“创建一个从指定的InputStream 读取的ObjectInputStream。从流中读取并验证序列化流标头。此构造函数将阻塞,直到相应的ObjectOutputStream 写入并刷新标头。 "

所以如果客户端和服务器都在ObjectOutputStream之前构造了ObjectInputStream,那么两者都会阻塞等待另一端发送序列化流标头。

请注意,这发生在对象流级别,而不是套接字或字节流级别。如果您在套接字上执行简单的字节或字符或“数据”I/O,则无需担心构建流的顺序。

同样不是,如果您在客户端和服务器端(都)有单独的线程来进行读取和写入,这不是问题。在所有条件相同的情况下,这可能是一个更好的架构,因为它允许客户端/服务器通过套接字进行“全双工”通信。

【讨论】:

  • 所以要求是至少在一端创建 ObjectOutputStream,而生活的规则应该是在两端首先创建它。
  • @EJP - 是的......但是如果客户端或服务器使用2个线程来构造+读取/构造+写入,那么您无需费心。
猜你喜欢
  • 2012-01-28
  • 2012-04-24
  • 1970-01-01
  • 2014-10-07
  • 2013-02-04
  • 2016-06-23
  • 2022-06-29
  • 2017-06-24
  • 2017-08-30
相关资源
最近更新 更多