为什么服务器死机时套接字不会死?为什么服务器处于活动状态时套接字会死?

时间:2010-03-17 12:56:29

标签: java sockets networking

我尝试使用套接字。为此,我编写了非常简单的“客户端”和“服务器”应用程序。

客户端:

import java.net.*;

public class client {
    public static void main(String[] args) throws Exception {
    InetAddress localhost = InetAddress.getLocalHost();
    System.out.println("before");

    Socket clientSideSocket = null;
    try {
        clientSideSocket = new Socket(localhost,12345,localhost,54321);
    } catch (ConnectException e) {
        System.out.println("Connection Refused");
    }
    System.out.println("after");

    if (clientSideSocket != null) {
        clientSideSocket.close();
    }
    }
}

服务器

import java.net.*;

public class server {
    public static void main(String[] args) throws Exception {
    ServerSocket listener = new ServerSocket(12345);

    while (true) {
        Socket serverSideSocket = listener.accept();
        System.out.println("A client-request is accepted.");
    }

    }
}

我发现了一个我无法解释的行为:

  1. 我启动服务器,而不是启动客户端。已成功建立连接(客户端停止运行且服务器正在运行)。然后我关闭服务器并在一秒钟内重新启动它。之后,我启动了一个客户端并写入“拒绝连接”。在我看来,服务器“记住”旧连接,并且不想两次打开第二个连接。但我不明白它是如何可能的。因为我杀死了以前的服务器并开始了一个新服务器!

  2. 我没有在前一个服务器被杀后立即启动服务器(我等了20秒)。在这种情况下,服务器“忘记”来自先前服务器的套接字并接受来自客户端的请求。

  3. 我启动服务器,然后启动客户端。建立连接(服务器写入:“接受客户端请求”)。然后我等一下再次启动客户端。服务器(一直运行)再次接受请求!为什么?服务器不应该接受来自同一客户端-IP和客户端端口的请求,但确实如此!

3 个答案:

答案 0 :(得分:4)

  1. 当您关闭服务器时,操作系统会将套接字保持活动一段时间,以便它可以告诉客户端连接已关闭。这涉及超时和重传,这可能需要一些时间。您可能会找到一些信息herehere。如果您希望服务器能够立即重新绑定同一个套接字,请在其上调用setReuseAddress(true),尽管它可能是处于TIME_WAIT状态的客户端套接字。

  2. 套接字不再处于TIME_WAIT状态,任何程序都可以重复使用。

  3. 您的客户端代码只是连接,关闭套接字然后退出。就服务器/ OS tcp堆栈而言,这些是不同的连接 - 只要任何先前的连接被拆除,就可以重用源端口。 (请注意,在您调用.close()或程序退出后,操作系统可能不会立即拆除连接的所有内务处理,因此可能会有一些时间延迟,因此可以确保所有数据包都已发送/接收)

答案 1 :(得分:0)

操作系统可能尚未关闭套接字,请尝试使用netstat命令(应该在Windows或Unix / Linux上运行)。如果在关闭客户端或服务器后立即运行它,则仍应使用“TIME_WAIT”“CLOSE_WAIT”或类似的套接字。在完全关闭之前,您将无法重用这些端口。

答案 2 :(得分:0)

针对问题#3:许多客户端可以连接到连接到单个端口的服务器。 Apache在端口80上运行,但这并不意味着一次只能有一个人查看您的网站。您也在关闭客户端套接字之前打开一个新套接字。