Исключение сокета: сокет закрыт, брошенный при чтении массива байтов

Во-первых, я довольно новичок, поэтому я не совсем уверен, какой код здесь разместить, потому что я думаю, что проблема может быть во многих разных местах. Несмотря на это, я делаю программу обмена мгновенными сообщениями и отправляю изображения. Сначала я конвертирую изображения в массивы байтов, затем отправляю их на сервер, который затем перенаправляет их клиенту. На стороне сервера у меня есть несколько потоков, прослушивающих объекты любого типа. Это метод run() для них:

@Override 
public void run(){      
    while(isAlive()){  
        try{
            received = input.readObject();
        }catch(IOException | ClassNotFoundException exception){
            exception.printStackTrace();
        }            
    }          
}

input — это ObjectInputStream, и у меня есть геттер для получения объекта received. Однако я получаю SocketException в строке received = input.readObject() только всякий раз, когда отправляю этот массив байтов. Вот трассировка стека:

java.net.SocketException: socket closed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:150)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at java.net.SocketInputStream.read(SocketInputStream.java:203)
    at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2296)
    at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2589)
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2599)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1319)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    at server.ReaderThread.run(ReaderThread.java:24)

Итак, вы знаете, что происходит. Для справки, в моем классе сервера я присваиваю другому объекту значение received через геттер, а затем проверяю, является ли это String, byte[] и т. д., используя instanceof (если это вообще имеет значение). Довольно похожая версия этого метода работала гораздо раньше, когда мессенджер был просто между клиентом и сервером. Я знаю, что пропустил много кода; просто спросите, и я отредактирую или прокомментирую.

Вот код в фактической серверной программе, которая назначает новый объект (имейте в виду, что receiveds и lastReceiveds являются ArrayLists, и это выполняется в цикле for(int i = 0)):

lastReceiveds.set(i, receiveds.get(i));
receiveds.set(i, readerThreads.get(i).getReceived());

И затем я продолжаю делать .equals для этого элемента receiveds и продолжаю обработку данных.

[EDIT] Итак, мне сказали, что я закрываю свои сокеты, потоки и т. д., и это правда. Вот код, который вызывает это (метод close(), который вызывается, просто закрывает все мои сокеты, потоки и т.д.):

            try{

                waitForConnection();
                setupStreams();
                System.out.println("Got to here");
                whileChatting();

            }catch(EOFException eofException){

                showMessage("\nERROR! CONNECTION REFUSED");
                eofException.printStackTrace();

            }finally{

                close();

            }

Извините, что все так расплывчато. Он выводит "Got to here", then runsclose()` всякий раз, когда получает массив байтов.


person dsiegler19    schedule 22.03.2016    source источник
comment
можешь выложить больше кодов?   -  person Haifeng Zhang    schedule 22.03.2016
comment
EOFException не означает «отказ в соединении». Это означает, что партнер закрыл соединение, что также означает, что соединение было, что также означает, что оно не было отклонено. «ConnectException: соединение отклонено» означает «соединение отклонено». Не придумывайте свои собственные сообщения об ошибках. Используйте тот, что в исключении, или само исключение.   -  person user207421    schedule 23.03.2016
comment
Спасибо. Я изменил это, чтобы просто распечатать трассировку стека и сказать ERROR! END OF FILE   -  person dsiegler19    schedule 23.03.2016
comment
Хорошо, это может быть из-за того, как я обрабатываю массив байтов, который вызывает IOException   -  person dsiegler19    schedule 23.03.2016
comment
Тоже не ошибка. Ожидается, что одноранговый узел отключится через некоторое время.   -  person user207421    schedule 23.03.2016


Ответы (1)


Это исключение означает, что вы закрыли сокет где-то в этом коде, а затем продолжили его использовать. Это не имеет ничего общего с узлом или тем, что он отправляет.

Вам также нужно поймать EOFException отдельно и выйти из цикла без регистрации, когда вы его получите. Любые другие IOException, кроме SocketTimeoutException, также фатальны для соединения и должны привести к разрыву.

person user207421    schedule 22.03.2016
comment
Итак, у меня есть метод close(), который закрывает все потоки, но я знаю, что он не вызывается, поэтому может ли это быть вызвано чем-то другим, например, NullPointerException или ArrayOutOfBoundsException? - person dsiegler19; 23.03.2016
comment
@ dsiegler19 Нет, это вызвано вызовом close() в сокете или любом из его потоков. Оператор try-with-resources также делает это. - person user207421; 23.03.2016
comment
На самом деле последний комментарий был ложью. Позвольте мне изучить его больше, чем отредактировать. - person dsiegler19; 23.03.2016