【问题标题】:client ends connection or server?客户端结束连接或服务器?
【发布时间】:2012-04-01 10:39:08
【问题描述】:

我正在编写客户端服务器应用程序。我想结束连接,应该由哪一方决定结束它,客户端还是服务器?

那么如果例如客户端这样做了,服务器是否仍然保持打开状态?

假设我们对每个客户端和服务器都有以下代码:

           socket = new Socket("127.0.0.1",3000);
........

            socket.close();

            serverSocket = new ServerSocket(3000);
            socket = serverSocket.accept();
......

            serverSocket.close();

编辑: 根据马特的回答,我把我的代码放在这里,看看为什么我的代码不起作用:

一般来说,我有一个 Jframe 程序作为客户端,它将连接到服务器,当它打开时,我希望连接处于活动状态,因为它将信息发送到服务器并且服务器应该响应结果。但是如果我不使用从服务器关闭套接字,它会给出一个错误,如果我使用,在一次计算后,它会关闭连接:

服务器

        private static PrintWriter toClient;
        private static BufferedReader fromClient;


  public static void run() throws IOException, SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException, SAXException, XPathExpressionException
        {
  
        
        System.out.println("Server is waiting for connections...");
   
        while(true)
        {
                 openStreams();
                  processClient();
                  closeStreams();
 }
     
    }

开放流:

  public static void openStreams() throws IOException, SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException, SAXException, XPathExpressionException
            {
            serverSocket = new ServerSocket(3000);
            socket = serverSocket.accept();
                System.out.println("Connected");

             toClient = new PrintWriter(socket.getOutputStream(),true);
            
            fromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            

            }

近亲:

   public static void closeStreams() throws IOException
            {
            fromClient.close();
            toClient.close();
            socket.close();
            serverSocket.close();
                System.out.println("Disconnected");
        }
          

如果我删除 closestream(); 会收到错误

at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:359)
    at java.net.ServerSocket.bind(ServerSocket.java:319)
    at java.net.ServerSocket.<init>(ServerSocket.java:185)
    at java.net.ServerSocket.<init>(ServerSocket.java:97)

【问题讨论】:

    标签: java client-server


    【解决方案1】:

    取决于您的应用程序的逻辑。两者都是有效的,并且您必须确保您的代码在这两种情况下都是正确的,因为如果连接“非自愿”中断(如网络中断),那么双方都会认为对方已经关闭了连接。

    所以你的代码必须优雅地处理这两种情况。

    您的关闭代码可疑:您正在关闭侦听套接字,这是不寻常的。仅当您不再需要任何传入连接时才应关闭侦听套接字(即通常对于服务器,当您关闭服务器时)。
    仅关闭您从accept 获得的套接字以结束该“对话”,并且不要重新打开服务器侦听套接字。 (在这种情况下,您遇到的异常可能是“地址已在使用中”。有关如何避免该特定问题的示例,请参阅 How to set reuse address option for a datagram socket in java code?。)

    【讨论】:

    • 但我很困惑,因为如果客户端结束它,那么服务器应该执行 socket.close 还是不?反之亦然
    • 一旦套接字在一侧关闭,如果另一侧尝试在其上运行需要打开连接的方法,则会出现异常。不管是服务器还是客户端;一旦连接打开,从 TCP 的角度来看,两者都是等效的。
    • 重新阅读我的回答:您必须优雅地处理所有情况。这意味着如果发生异常则处理它们,并关闭您不再使用的流。 (顺便说一句:请报告实际的异常,而不仅仅是堆栈跟踪 - 两者都是有意义的错误消息所必需的。)
    • 堆栈跟踪的第一行应该包含实际的异常;或者你正在做一些有趣的事情来打印它。
    • @user1064929:请阅读我的回答和我之前的评论,并尝试实现你的代码,这样你就不会关闭 不要重新打开服务器侦听套接字(代码中的serverSocket)。这应该可以解决问题。
    【解决方案2】:

    任何一端都可以关闭连接 - 两者都不是“更正确”。

    但是,澄清代码中的一个(看似)误解很重要: 关闭 ServerSocket 并不是关闭代表两个端点之间连接的套接字。

    ServerSocket 是端口上的侦听套接字。当客户端与该端口上的 ServerSocket 建立连接时,ServerSocket.accept() 方法会返回一个(正常)Socket。两个端点之间的通信使用与此(正常)套接字关联的输入和输出流。

    关闭 ServerSocket 只是停止侦听众所周知的端口,并且与已建立的套接字无关。

    【讨论】:

      【解决方案3】:

      套接字存在于客户端和服务器程序中。关闭任何套接字都会在另一端抛出异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-06
        • 1970-01-01
        • 1970-01-01
        • 2018-05-18
        • 2020-06-26
        • 2012-03-27
        • 2012-05-22
        • 2016-12-10
        相关资源
        最近更新 更多