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.

Al-Alamin
  • 1,438
  • 2
  • 15
  • 34
  • 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. – Luciano Afranllie May 10 '18 at 15:43

1 Answers1

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 */ }
        }

    }

}
JayC667
  • 2,418
  • 2
  • 17
  • 31
  • 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 – Al-Alamin May 10 '18 at 07:04
  • 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... – JayC667 May 10 '18 at 20:09