0

我有一个接受 TCP 连接并将这个新套接字发送到线程 B 的类 A,在那里接收和发送来自该套接字的数据。

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)

我不明白为什么在多年工作正常之后现在会发生这种情况。这是由于网络问题还是线程相关的东西?

更新:这可能是与服务器相关的问题吗?因为相同的应用程序正在其他服务器上运行,但他们没有这个问题。

4

1 回答 1

1

整个设置概念看起来有点破损。您不应该从外部“更改”资源,而该线程中可能还有一些工作要做。一个更好的概念是将 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 */ }
        }

    }

}
于 2018-05-10T06:39:20.780 回答