为什么Java ServerSocket accept()返回一个与ServerSocket具有相同端口的套​​接字?

时间:2012-12-30 15:10:48

标签: java sockets tcp serversocket

在服务器端,我使用此代码:

ServerSocket server = new ServerSocket(1234);
Socket server_socket = server.accept();

我发现服务器正在侦听端口1234.

当连接一个或多个客户端套接字时,它们都使用相同的端口1234!

这真令人困惑:

enter image description here

我记得多套接字不能使用同一个端口,不是吗?感谢。

1 个答案:

答案 0 :(得分:11)

TCP连接由四个数字标识:

  • 客户端(或对等方1)IP
  • 服务器(或对等2)IP
  • 客户端端口
  • 服务器端口

典型的TCP连接打开如下:

  • 客户端IP由客户端的ISP或NAT提供。
  • 服务器IP由用户提供或在DNS中查找。
  • 客户端从未分配的范围中任意选择一个端口(同时避免重复四倍)
  • 服务器端口由协议提供或明确提供。

您在ServerSocket中指定的端口是客户端连接到的端口。它只不过是操作系统知道属于您的应用程序的端口号,以及将事件从操作系统传递到应用程序的对象。

ServerSocket#accept方法返回Socket。 Socket是一个包装单个TCP连接的对象。也就是客户端IP,服务器IP,客户端TCP端口和服务器TCP端口(以及传递相关数据的一些方法)

客户端发送的第一个TCP数据包必须包含应用程序侦听的服务器端口,否则操作系统将不知道该连接属于哪个应用程序。

此外,没有动力将服务器TCP端口切换到另一个号码。它对服务器机器或客户端机器没有帮助,它需要一些开销来执行(你需要将新的和旧的TCP端口一起发送),并且还有额外的开销,因为服务器操作系统无法再通过以下方式识别应用程序单个端口 - 它需要将应用程序与其使用的所有服务器端口相关联(客户端仍需要执行此操作,但典型客户端的连接数少于典型服务器)


你看到的是

  • 属于服务器的两个入站连接(本地端口:1234)。每个服务器应用程序中都有自己的Socket
  • 属于客户端的两个出站连接(远程端口:1234)。每个客户端应用程序中都有自己的Socket
  • 属于服务器的一个侦听连接。这对应于接受连接的单个ServerSocket

由于它们是环回连接,因此您可以在一台计算机上看到两个端点混合在一起。您还可以在本地和远程端看到两个不同的客户端端口(52506和52511)。