Подтвердить что ты не робот

Java Создание новых блоков ObjectInputStream

Я пытаюсь создать новый ObjectInputStream, используя InputStream, извлеченный из Socket. Вот мой код:

Это конструктор для моего класса 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);

...

Поскольку код не выполняется для Checkpoint 4, но он попадает на Checkpoint 3, я уверен, что создание ObjectInputStream является виновником. Однако я не могу понять, почему. Есть идеи? Спасибо за помощь.

4b9b3361

Ответ 1

Когда вы строите ObjectInputStream, в конструкторе класс пытается прочитать заголовок, который написал связанный ObjectOutputStream на другом конце соединения. Он не вернется, пока этот заголовок не будет прочитан. Поэтому, если вы видите, что конструктор "зависает", он потому, что другая сторона сокета либо не использовала ObjectOutputStream, либо еще не сбросила данные.

Ответ 2

Просто для продолжения ответа FatGuy для других гуглеров, которые находят это; решение этой "проблемы с курицей и яйцом" состоит в том, чтобы каждая сторона сначала открывала выходной поток, очищала выходной поток, а затем открывала входной поток.

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

Ответ 3

Вы также можете задержать инициализацию ObjectInputStream до тех пор, пока данные не будут доступны в базовом потоке.

Этот подход работает независимо от порядка инициализации потока и особенно полезен, если один конец канала находится в библиотечном коде, который вы не можете изменить.