Странное поведение сокета Java (подключается, но не отправляет)

У меня есть довольно сложный проект, который сводится к простому взаимодействию клиента/сервера через потоки объектов.

Все работает без нареканий при двух последовательных подключениях (один раз подключаюсь, работаю, отключаюсь, потом снова подключаюсь, работаю и отключаюсь). Клиент подключается, занимается своими делами, а затем закрывается. Сервер успешно закрывает поток вывода объекта и сокет без ошибок ввода-вывода.

Когда я пытаюсь подключиться в третий раз, кажется, что соединение проходит (метод ServerSocket.accept() проходит, и ObjectOutputStream успешно создается). Однако данные не передаются. Метод inputStream.readUnshared() просто блокирует.

Я принял следующие меры предосторожности для памяти:

  1. Когда приходит время закрывать сокеты, все запущенные потоки останавливаются, а все объекты обнуляются.
  2. После каждого вызова метода writeUnshared() ObjectOutputBuffer очищается и сбрасывается.

Кто-нибудь сталкивался с подобной проблемой, или у кого есть предложения? Боюсь, мой проект довольно большой, и поэтому копирование кода проблематично.

Проект сводится к следующему:

ГЛАВНЫЙ СЕРВЕР

ServerSocket serverSocket = new ServerSocket(port);

while (true) {
    new WorkThread(serverSocket.accept()).start();
}

РАБОЧИЙ ПОТОК (СЕРВЕР)

public void run() {
    ObjectInputBuffer inputBuffer = new ObjectInputBuffer(new BufferedInputStream(socket.getInputStream()));

    while (running) {
         try {
              Object myObject = inputBuffer.readUnshared();

              // do work is not specified in this sample
              doWork(myObject);
         } catch (IOException e) {   
              running = false;
         }
    }

    try {
         inputBuffer.close();
         socket.close(); 
    } catch (Exception e) {
         System.out.println("Could not close.");
    }
}

КЛИЕНТ

public Client() {
    Object myObject;
    Socket mySocket = new Socket(address, port);

    try {
         ObjectOutputBuffer output = new ObjectOutputBuffer(new BufferedOutputStream(mySocket.getOutputStream()));

         output.reset();
         output.flush();
    } catch (Exception e) {
         System.out.println("Could not get an input.");
         mySocket.close();
         return;
    }

    // get object data is not specified in this sample. it simply returns a serializable object
    myObject = getObjectData();

    while (myObject != null) {
         try {
              output.writeUnshared(myObject);
              output.reset();
              output.flush();
         } catch (Exception e) {
              e.printStackTrace();
              break;
         } // catch
    } // while

    try {
         output.close();
         socket.close();
    } catch (Exception e) { 
         System.out.println("Could not close.");
    }
}

Спасибо всем, кто может помочь!


person Donald Campbell    schedule 21.05.2010    source источник
comment
есть ли причина, по которой вы используете readUnshared вместо readObject? Мне это кажется довольно опасным.   -  person mdma    schedule 22.05.2010


Ответы (2)


(1) Что такое ObjectInputBuffer и ObjectOutputBuffer? Вы имели в виду ObjectInputStream и ObjectOutputStream?

(2) Если это так, то вызов reset() сразу после создания ObjectOutputStream — пустая трата времени и полосы пропускания.

(3) Почему вы печатаете «не удалось получить ввод» для исключения, создающего выходной поток?

(4) Когда вы получаете исключение, вы всегда должны печатать его сообщение — не заменяйте его полностью своим, это просто отбрасывает полезную информацию.

(5) Вы предполагаете, что любое IOException при чтении означает конец потока. Только EOFException означает это. Любое другое исключение IOException должно быть распечатано или зарегистрировано. Очевидно, вы получаете здесь какое-то другое исключение и игнорируете его.

(6) Почему вы продолжаете отправлять один и тот же объект?

person user207421    schedule 22.05.2010

Из API ObjectInputStream для readUnshared():

Считывает «нераспространяемый» объект из ObjectInputStream. Этот метод идентичен readObject, за исключением того, что он не позволяет последующим вызовам readObject и readUnshared возвращать дополнительные ссылки на десериализованный экземпляр, полученный с помощью этого вызова.

Может ли это быть проблемой? Вместо этого используйте readObject().

person Jivings    schedule 22.05.2010