0

I have a class A that accepts TCP connection and send this new socket to Thread B where data from that socket is received and sent.

Class A{
    Class b = new B();   
    public void run()
    {
        b.start();
        while(true){

            Socket socket = serverSocket.accept();
            if(socket==null || socket.isClosed())continue;
            b.setSocket(socket);

        }

    }
}

Class B extends Thread{
  Socket socket;
  public void setSocket(Socket p_socket) throws IOException
  {
      if(socket!=null && !socket.isClosed())
      {
          try{
          socket.close();
          socket = null;
          Thread.sleep(5);
          }
          catch(Exception ex)
          {}
      }
    socket = p_socket;
    inputStream = socket.getInputStream(); // Here I am getting socket.closed() exception very much.
}

This worked fairly good in the past but now recently I am very very frequently getting the following error.

java.io.IOException: Socket Closed
        at java.net.AbstractPlainSocketImpl.getInputStream(AbstractPlainSocketImpl.java:421)
        at java.net.Socket$2.run(Socket.java:914)
        at java.net.Socket$2.run(Socket.java:912)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.Socket.getInputStream(Socket.java:911)

I don't understand why this is happening now after years of working fine. Is this due to the network problem or Thread related something?

Updated: Can this be the server related problem? Because the same application is running on other server but they are not having this problem.

1
  • The socket could be closed between p_socket is assigned to socket and call to socket.getInputStream(). Maybe the server or something in between is closing connections more often now and this situation is manifested now. Commented May 10, 2018 at 15:43

1 Answer 1

1

The whole setup concept looks a bit broken. You should not "change" resources from the outside, while maybe there is still some work going on in that thread. A way better concept is to encapsulate the Socket into a new worker thread:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;



public class WrapHandler {

    static public class Server {

        private final ServerSocket          mSocket;
        private final ArrayList<Handler>    mRunningHandlers    = new ArrayList<>();

        public Server(final int pPort) throws IOException {
            mSocket = new ServerSocket(pPort);
            new Thread(() -> mainLoop()).start();
        }

        private void mainLoop() {
            while (true) {
                try {
                    @SuppressWarnings("resource") final Socket socket = mSocket.accept(); // do not close, do not handle with resource, socket will be closed by handler!
                    final Handler h = new Handler(socket, this);
                    handlerStarted(h);
                } catch (final IOException e) {
                    e.printStackTrace(); // do something useful
                }
            }
        }

        synchronized void handlerStarted(final Handler pHandler) {
            mRunningHandlers.add(pHandler);
        }
        synchronized void handlerEnded(final Handler pHandler) {
            mRunningHandlers.remove(pHandler);
        }

        void handleException(final Handler pHandler, final Throwable pException) {
            /* again do something useful */
        }

    }

    static public class Handler {

        private final Socket    mSocket;
        private final Server    mServer;

        public Handler(final Socket pSocket, final Server pServer) {
            mSocket = pSocket;
            mServer = pServer;
            new Thread(() -> handleSocket()).start();
        }

        private void handleSocket() {
            try {
                handleData();
            } catch (final IOException e) {
                mServer.handleException(this, e);
            } finally {
                mServer.handlerEnded(this);
                stop();
            }
        }

        private void handleData() throws IOException {
            mSocket.getInputStream().read();
            /* data handling code here */
        }

        void stop() {
            try {
                mSocket.close();
            } catch (final IOException e) { /* ignore or handle as you will */ }
        }

    }

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

2 Comments

I want to understand why the problem is appearing now. This application has been running fine for years. In other server it is still running fine
How are the streams from the socket accessed? If you wrap them in some other Readers/Streams and close those, they might close the underlying socket's streams someplace else...

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.