1

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.

1
  • I think you should do your work with input and output stream in 1 thread in order to close the socket correctly. If you want to process input and output in parallel: start new threads from the thread where you processing input/output and use proper synchronization to close socket when all the work is done. Commented Nov 24, 2014 at 9:26

3 Answers 3

5

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.

Construct the BufferedReader outside the loop.

You probably don't need two threads per socket.

Sign up to request clarification or add additional context in comments.

3 Comments

Constructing BufferedReader outside the loop did not help. I am still getting the same error.
You closed the socket and continued to use it. => where I am using it after I closed it?
You need to do more than just one of the three things I have recommended here. Try reading the entire answer. You are using the socket after closure in the place where the exception was thrown from. That's why it was thrown. Surely this is obvious?
-1

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.

1 Comment

Exactly. A pretty vague answer. All threads run in parallel. That's why they're threads.
-1

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.

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

3 Comments

Yes, when producer send message to the client, I no not expect any communication between that client and server. So I want to close that socket. And I do it in finally block. However, if I delete that line that closes a socket, then I still get the same error.
Closing the output stream will close the socket. And its input stream.
That is expected. Because when your threads (Producer/Consumer) ends, the socket closes. Try having your prod/consume logic inside an infinite loop in your Producer and Consumer. Something like, while(true) {Producer/Consumer operations}. And close the socket from the server

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.