почему Java-сервер TCP принимает закрытый сокет? - PullRequest
0 голосов
/ 10 мая 2018

У меня есть класс A, который принимает TCP-соединение и отправляет этот новый сокет в поток B, где данные из этого сокета принимаются и отправляются.

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.
}

В прошлом это работало довольно хорошо, но в последнее время я очень часто получаю следующую ошибку.

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)

Я не понимаю, почему это происходит сейчас после нескольких лет работы в порядке. Это связано с проблемой сети или чем-то связанным с Thread?

Обновлено: Может ли это быть проблема, связанная с сервером? Потому что такое же приложение работает на другом сервере, но у них нет этой проблемы.

1 Ответ

0 голосов
/ 10 мая 2018

Вся концепция установки выглядит немного нарушенной. Вы не должны «менять» ресурсы извне, хотя, возможно, в этом потоке еще есть работа. Лучшим вариантом является инкапсуляция Socket в новый рабочий поток:

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

    }

}
...