Мой код выглядит следующим образом. Когда запрос приходит, сервер создает два потока (шаблон производителя-потребителя):
...
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)
Что может вызвать это? Я даже вижу, что клиент принимает сообщение правильно. Кроме того, в потоке производителя я закрываю сокет. Я не понимаю.
Вы закрыли розетку и продолжали ее использовать.
Не закрывайте сокет или его выходной поток до тех пор, пока вы не прочитаете конец потока из BufferedReader.
Постройте BufferedReader
вне цикла.
Вероятно, вам не нужны два потока на один сокет.
BufferedReader
вне цикла не помогло. Я все еще получаю ту же ошибку.
Проблема в том, что вы закрываете сокет из своей продукции после того, как что-то написали. Если вы хотите, чтобы сокет был открыт, просто закройте выходной поток в блоке finally в Producer. Вы можете закрыть сокет от Server/Producer/Consumer, как только вы убедитесь, что сетевого сокета не происходит через сокет.
https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#close()
Вы запускаете оба потока параллельно. Вы не можете предсказать поведение потоков. Вы используете тот же сокет для обоих потоков, и если поток производителей начинается, вы закрываете сокет в секции finally. вы не должны закрывать соединение и убедитесь, что состояние гонки не должно происходить.