多线程 TCP 服务器:java.net.SocketException:套接字已关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27100917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 11:12:53  来源:igfitidea点击:

multithreaded TCP server: java.net.SocketException: Socket closed

javamultithreadingsocketstcpsocketexception

提问by Bob

My code is as follows. When request comes, server creates two threads (producer-consumer pattern):

我的代码如下。当请求到来时,服务器创建两个线程(生产者-消费者模式):

...
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();
}
...

Consumer thread reads what client sent and producer thread responds back. Consumer:

消费者线程读取客户端发送的内容,生产者线程响应。消费者:

@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();
            }
        }

    }

Producer:

制作人:

 @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();
            }
        }

But in server I get following error:

但是在服务器中我收到以下错误:

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)

What might cause this? I even see that client accepts message correctly. Also, in producer thread I close a socket. I do not understand.

什么可能导致这种情况?我什至看到客户端正确接受消息。另外,在生产者线程中,我关闭了一个套接字。我不明白。

回答by user207421

You closed the socket and continued to use it.

您关闭了套接字并继续使用它。

Don't close the socket, or its output stream, until you have read end of stream from the BufferedReader.

不要关闭套接字或其输出流,直到您从 BufferedReader.

Construct the BufferedReaderoutside the loop.

构建BufferedReader循环的外部。

You probably don't need two threads per socket.

您可能不需要每个套接字有两个线程。

回答by Shriram

You are starting both the threads in parallel. You can't predict the behvaiour of threads. You are using the same socket for both the threads and if producer thread starts you are closing socket in finally section. you should not close the connection and make sure the race condition should not occur.

您正在并行启动两个线程。您无法预测线程的行为。您为两个线程使用相同的套接字,如果生产者线程启动,您将在 finally 部分关闭套接字。您不应关闭连接并确保不发生竞争条件。

回答by Ponmani Palanisamy

The problem is because you are closing the socket from your produce after writing something to it. If you want the socket to be open, just close the output stream in the finally block in Producer. You can close the socket from Server/Producer/Consumer once you are sure that there is no more network I/O to happen over the socket.

问题是因为您在向其写入内容后关闭了产品的套接字。如果您希望套接字打开,只需关闭 Producer 中 finally 块中的输出流。一旦确定没有更多的网络 I/O 发生在套接字上,您就可以从服务器/生产者/消费者关闭套接字。

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

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