ServerSocket是否接受任意端口上的返回套接字?

时间:2013-07-18 18:28:15

标签: java sockets networking tcp

我在java中看到了很多类似于这个问题的答案:“假设你在端口5000上有一个带有serversocket的服务器。客户端A和客户端B将连接到我们的服务器。

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

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

我在stackoverflow上的多个问题中看到了类似这样的答案,关于如何在accept()的返回套接字中使用不同的端口,而不是ServerSocket正在侦听的端口。我总是认为TCP是由四方信息确定的:

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

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

2 个答案:

答案 0 :(得分:15)

  

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

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

  

此处,客户端A连接到新端口

没有。在确认SYN / ACK之后,客户端确认SYN / ACK数据包,然后客户端从那时起连接到原始端口。没有第二次连接。

  

并且服务器现在再次使用端口5000。“

总是如此。

  

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

任何这样的答案都是不正确的,应该在“极端偏见”的情况下进行投票,并对此进行评论。 TCP握手在RFC 793中定义,并未指定第二端口和第二连接消息的分配和交换。只有三条消息,甚至不足以让它发生。

  

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

没有。

  

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

答案 1 :(得分: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之上。