java - 为什么java tcp服务器接受关闭的套接字?

标签 java tcp serversocket java-security-manager

我有一个类 A,它接受 TCP 连接并将这个新套接字发送到线程 B,在线程 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)

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

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

最佳答案

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

    }

}

关于java - 为什么java tcp服务器接受关闭的套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50266631/

相关文章:

pmd - PMD规则背后的 "Why"

java - JMeter:使用 jackson jar 时出现 NoClassDefFoundError 错误

java - 布局中的 Android 微调器

android - 通过 TCP 从 Android 到 PC 的音频流

java - 客户端无法连接到服务器套接字 - Android

java - 如何在关闭后再次打开服务器套接字?

Java - JProgressBar 不会更改值,JLabel 不会更改文本

windows - 在 Windows TCP/IP 中以编程方式更改名称服务器

java - 在 Windows 中通过命令行连接到套接字并发送数据

Java:如何创建一个仅在其实例不存在时启动并在实例存在时调用该实例的应用程序?