многопоточный TCP-сервер: java.net.SocketException: сокет закрыт

1

Мой код выглядит следующим образом. Когда запрос приходит, сервер создает два потока (шаблон производителя-потребителя):

...
while(true) {
    Socket clientSocket = server.accept();
    System.out.println("Got connection!");

    Thread consumerThread = new Thread(new ConsumerThread(sharedQueue, clientSocket));
    Thread producerThread = new Thread(new ProducerThread(sharedQueue, clientSocket));

    consumerThread.start();
    producerThread.start();
}
...

Потребительский поток читает, что клиент отправил, и поток производителей отвечает. Потребитель:

@Override
    public void run() {
        try {
            while (true) {
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                // read, do actions
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

Режиссер:

 @Override
    public void run() {
        try {
            out = new PrintStream(clientSocket.getOutputStream(), true);
            // some actions
            out.println("something");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

Но на сервере я получаю следующую ошибку:

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 sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at ee.ut.ds.server.ConsumerThread.run(ConsumerThread.java:30)
    at java.lang.Thread.run(Thread.java:745)

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

  • 0
    Я думаю, что вы должны сделать свою работу с входным и выходным потоком в 1 поток, чтобы правильно закрыть сокет. Если вы хотите обрабатывать ввод и вывод параллельно: запустите новые потоки из потока, в котором вы обрабатываете ввод / вывод, и используйте правильную синхронизацию, чтобы закрыть сокет после завершения всей работы.
Теги:
multithreading
sockets
tcp
socketexception

3 ответа

5
Лучший ответ

Вы закрыли розетку и продолжали ее использовать.

Не закрывайте сокет или его выходной поток до тех пор, пока вы не прочитаете конец потока из BufferedReader.

Постройте BufferedReader вне цикла.

Вероятно, вам не нужны два потока на один сокет.

  • 0
    Построение BufferedReader вне цикла не помогло. Я все еще получаю ту же ошибку.
  • 0
    Вы закрыли сокет и продолжили использовать его. => где я использую его после того, как я его закрыл?
Показать ещё 1 комментарий
0

Проблема в том, что вы закрываете сокет из своей продукции после того, как что-то написали. Если вы хотите, чтобы сокет был открыт, просто закройте выходной поток в блоке finally в Producer. Вы можете закрыть сокет от Server/Producer/Consumer, как только вы убедитесь, что сетевого сокета не происходит через сокет.

https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#close()

  • 0
    Да, когда производитель отправляет сообщение клиенту, я не ожидаю никакой связи между этим клиентом и сервером. Поэтому я хочу закрыть эту розетку. И я делаю это в, наконец, блоке. Однако, если я удаляю эту строку, которая закрывает сокет, я все равно получаю ту же ошибку.
  • 0
    Закрытие выходного потока закроет сокет. И его входной поток.
Показать ещё 1 комментарий
-1

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

  • 1
    Можете ли вы предложить, как я должен изменить свой код?
  • 0
    Именно так. Довольно расплывчатый ответ. Все потоки работают параллельно. Вот почему они темы.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню