【问题标题】:Java Creating a new ObjectInputStream BlocksJava 创建一个新的 ObjectInputStream 块
【发布时间】: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 的实例化是罪魁祸首。我不知道为什么。有任何想法吗?感谢您的帮助。

【问题讨论】:

    标签: java debugging sockets inputstream


    【解决方案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 了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2013-07-19
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多