7

关于 java 中的 serversockets,我已经看到了许多与此类似的答案:“假设您有一个服务器,其 serversocket 在端口 5000 上。客户端 A 和客户端 B 将连接到我们的服务器。

客户端 A 在端口 5000 上向服务器发送请求。客户端 A 端的端口由操作系统选择。通常,操作系统会选择下一个可用的端口。此搜索的起点是先前使用的端口号 + 1(例如,如果操作系统最近遇到了我们的端口 45546,那么操作系统将尝试 45547)。

假设没有连接问题,服务器收到客户端 A 的连接请求,连接端口 5000。然后服务器打开自己的下一个可用端口,并将其发送给客户端。在这里,客户端 A 连接到新端口,而服务器现在又可以使用 5000 端口了。”

我在 stackoverflow 上的多个问题中看到了这样的答案,关于如何在 accept() 的返回套接字中使用与 ServerSocket 正在侦听的端口不同的端口。我一直认为 TCP 是由四重信息标识的:

客户端 IP:客户端端口和服务器 IP:服务器端口 -> 协议(区分 TCP 和 UDP)

那么为什么 accept() 需要返回绑定到不同端口的套​​接字呢?在每个标头中发送的四重信息是否不足以区分来自不同机器的到同一服务器端口的多个连接,因为它不需要使用服务器机器上的不同端口进行通信?

4

2 回答 2

17

然后服务器打开自己的下一个可用端口,并将其发送给客户端。

不,它会创建一个具有相同本地端口号的新套接字。没有第二个端口号被分配或发送给客户端。作为服务器对连接请求的响应的 SYN/ACK 段不包含第二个端口号。

在这里,客户端 A 连接到新端口,

不,客户端确认 SYN/ACK 数据包,然后客户端在确认 SYN/ACK 后连接到原始端口。没有第二个连接。

并且服务器现在有端口 5000 再次可用。”

它总是这样。

我在 stackoverflow 上的多个问题中看到了这样的答案,关于如何在 accept() 的返回套接字中使用与 ServerSocket 正在侦听的端口不同的端口。

任何这样的答案都是不正确的,应该“带着极端偏见”被否决,并给予负面评论。TCP 握手在RFC 793中定义,并没有指定第二个端口和第二个连接消息的分配和交换。只有三个消息,这甚至不足以发生这种情况。

那么为什么 accept() 需要返回绑定到不同端口的套​​接字呢?

它没有。

在每个标头中发送的四重信息是否不足以区分来自不同机器的同一个服务器端口的多个连接,因为它不需要使用服务器机器上的不同端口进行通信?

是的。

于 2013-07-18T22:06:33.393 回答
5

您在 TCP 数据包标头的信息中是正确的。它包含:

Client IP | Client Port | Server IP | Server Port | Protocol

或者,更合适的是(因为当您考虑双向传输时客户端/服务器会变得混乱):

Source IP | Source Port | Destination IP | Destination Port | Protocol

到同一服务器端口的多个连接将来自客户端上的不同端口。一个例子可能是:

0.0.0.0:45000 -> 1.1.1.1:80
0.0.0.0:45001 -> 1.1.1.1:80

客户端端口的差异足以消除两个套接字的歧义,因此具有两个单独的连接。服务器无需在另一个端口上打开另一个套接字。它确实从该accept方法接收了一个套接字,但它被分配到同一个端口,现在是返回新接受的客户端的路由。

另一方面,FTP 确实有一个模型,服务器将打开一个新的非特权端口(> 1023)并将其发送回客户端以供客户端连接(这称为“被动 FTP”)。这是为了解决客户端位于防火墙后面并且无法接受来自服务器的传入数据连接的问题。但是,在典型的 HTTP 服务器(或任何其他标准套接字实现)中情况并非如此。它的功能位于 FTP 之上。

于 2013-07-18T18:49:34.707 回答