【问题标题】:How to reopen a Java socket如何重新打开 Java 套接字
【发布时间】:2011-03-09 10:42:01
【问题描述】:

我正在循环读取 Java 套接字。

如果读取引发异常,我想重新打开套接字。

为了测试这一点,我只是关闭了套接字并捕获了异常。

问题是,当我尝试重新打开套接字时:

serverSocket = new ServerSocket(port)
socket = serverSocket.accept()

它抛出一个异常:

java.net.BindException: The socket name is already in use

这是一个直接的测试问题。但它也可能发生在生产中。

如何在异常发生后通过打开新的套接字连接可靠地恢复 被扔了?

【问题讨论】:

  • 如果线程抛出异常,你应该close() serversocket,然后等待10秒重新打开同一个端口。
  • 如果服务器出于某种原因关闭套接字并且客户端检测到 isClosed () 那么它本身不能重新打开,而是客户端必须创建一个新的套接字。 10 秒似乎是任意的。指数退避重试模式会更合适。

标签: java sockets


【解决方案1】:

如果我误解了你的意思,我很抱歉。

如果套接字上的 read() 方法失败,则不会关闭 ServerSocket。

您应该仍然能够调用 serverSocket.accept() 而无需创建新的。我认为这就是您收到 BindException 的原因。

【讨论】:

    【解决方案2】:

    您需要创建一次 ServerSocket,并将任何接受的套接字传递给它的处理程序 - 通常在不同的线程中完成。

    你得到的错误是因为你试图在同一个端口上监听两次,这是不可能的。

    这个article 可以帮助你。这是其中一个代码示例:

    public void await() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            serverSocket =  new ServerSocket(port, 1,
            InetAddress.getByName("127.0.0.1"));
        }
        catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    
        // Loop waiting for a request
        while (!shutdown) {
            Socket socket = null;
            InputStream input = null;
            OutputStream output = null;
            try {
                socket = serverSocket.accept();
                input = socket.getInputStream();
                output = socket.getOutputStream();
    
                // create Request object and parse
                Request request = new Request(input);
                request.parse();
    
                // create Response object
                Response response = new Response(output);
                response.setRequest(request);
                response.sendStaticResource();
    
                // Close the socket
                socket.close();
    
                //check if the previous URI is a shutdown command
                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
            }
            catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我发现工作是这样的:

      1. 关闭ServerSocket
      2. 创建一个新的 ServerSocket

      关闭 ServerSocket 后无需延迟。那是在 IBM AIX 机器上——在其他平台上的行为可能不同。

      无需关闭 Socket。

      我还向 Socket 添加了超时,以从连接失败的另一端恢复。这是在启动和异常时运行的代码:

      if (serverSocket != null) serverSocket.close();
      serverSocket = new ServerSocket(port);
      socket = serverSocket.accept();
      socket.setSoTimeout(TIMEOUT);
      is = socket.getInputStream();
      

      也感谢关闭 ServerSocket 的提示。这让我走上了正轨。以及有用的网络编程参考。

      【讨论】:

      • 我很困惑...为什么您需要关闭 ServerSocket 而不是客户端 Socket?客户端应该是启动重新连接的一方,您不必关闭/重新打开 ServerSocket。如果您要上传大量数据并需要恢复,我只需让服务器在接受“新”连接后将会话 ID 传输给客户端。连接断开后,服务器应该存储会话的当前状态,然后当客户端尝试重新连接时,它会在打开“恢复”连接时传输之前的会话 ID。
      【解决方案4】:

      在连接会话期间抛出异常时,您应该关闭套接字。

      【讨论】:

        猜你喜欢
        • 2015-04-13
        • 1970-01-01
        • 2012-11-23
        • 1970-01-01
        • 2019-03-05
        • 2012-01-17
        • 2013-04-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多