当客户端在给定端口上连接到服务器时,客户端连接来自 IP 地址和客户端端口号。客户端端口号由客户端自动生成,并且对于该客户端来说是唯一的。因此,您最终会得到四个可以建立联系的项目。
Server IP address (well known to all clients)
Server port (well known to all clients)
Client IP address (unique for that client)
Client port (dynamically unique for that client and that socket)
因此,正是这四项的组合构成了唯一的 TCP 连接。如果同一客户端对同一服务器和端口建立第二个连接,则该第二个连接将具有不同的客户端端口号(客户端建立的每个连接将被赋予不同的客户端端口号),因此上述四项的组合第二个客户端连接将有所不同,从而使其流量与客户端建立的第一个连接完全分开。
因此,TCP 套接字是上述四项的独特组合。要了解如何使用它,让我们看看一些流量是如何流动的。
客户端连接到服务器并创建 TCP 套接字来表示该连接后,客户端会发送数据包。该数据包是从客户端 IP 地址和该特定套接字正在使用的唯一客户端端口号发送的。当服务器在自己的端口号上接收到该数据包时,它可以看到该数据包来自客户端 IP 地址和该特定客户端端口号。它可以使用这些项目在其表中查找并查看该流量与哪个 TCP 套接字关联,并触发该特定套接字的事件。这将该客户端的流量与所有其他当前连接的套接字分开(无论它们是来自同一客户端的其他连接还是来自其他客户端的连接)。
现在,服务器想要向该客户端发送响应。数据包被发送到客户端的 IP 地址和客户端端口号。客户端 TCP 堆栈执行相同的操作。它从服务器 IP/端口接收数据包并发送到特定的客户端端口号,然后将该数据包与客户端上适当的 TCP 套接字相关联,以便它可以在正确的套接字上触发事件。
即使许多客户端可能连接到相同的服务器 IP 和端口,所有流量都可以通过这种方式唯一地与适当的客户端或服务器 TCP 套接字关联。客户端 IP/端口的唯一性允许两端知道给定数据包属于哪个套接字。
webSocket 连接以 HTTP 连接(这是运行 HTTP 协议的 TCP 套接字)开始。该初始 HTTP 请求包含一个“升级”标头,请求服务器将协议从 HTTP 升级到 webSocket。如果服务器同意升级,则返回响应,表明协议将更改为webSocket协议。 TCP 套接字保持不变,但双方都同意他们现在将使用 webSocket 协议而不是 HTTP 协议。因此,一旦连接,您就拥有了一个 TCP 套接字,双方都在使用 webSocket 协议。此 TCP 连接使用上述相同的逻辑来保持与同一服务器的其他 TCP 连接的唯一性。
通过这种方式,您可以在单个端口上拥有一个同时适用于 HTTP 连接和 webSocket 连接的服务器。到该服务器的所有连接都以 HTTP 连接开始,但在双方同意更改协议后,有些连接会转换为 webSocket 连接。保留 HTTP 连接的 HTTP 连接将是典型的请求/响应,然后套接字将被关闭。 “升级”到 webSocket 协议的 HTTP 连接将在 webSocket 会话期间保持打开状态(可以长期存在)。您可以拥有许多并发打开的 webSocket 连接,这些连接彼此不同,而新的 HTTP 连接均由同一台服务器定期提供服务。上面的 TCP 逻辑用于跟踪哪些数据包发往/来自同一服务器/端口属于哪个连接。
仅供参考,您可能听说过 NAT(网络地址转换)。这通常用于允许专用网络(如家庭或公司网络)连接到公共网络(如互联网)。通过 NAT,服务器可能会将多个客户端视为具有相同的客户端 IP 地址,即使它们是专用网络上物理上不同的计算机。使用NAT,多台计算机通过公共IP地址进行路由,但NAT仍然保证客户端IP地址和客户端端口号仍然是唯一的组合,因此上述方案仍然有效。使用 NAT 时,发往特定客户端的传入数据包将到达共享 IP 地址。然后,IP/端口被转换为专用网络上的实际客户端 IP 地址和端口号,然后数据包被转发到该设备。服务器通常不知道这种转换和数据包转发。由于 NAT 服务器仍然保持客户端 IP/客户端端口组合的唯一性,因此即使看起来许多客户端共享一个公共 IP 地址,服务器的逻辑仍然可以正常工作。请注意,家庭网络路由通常配置为使用 NAT,因为家庭网络上的所有计算机在访问互联网时都会“共享”路由器拥有的一个公共 IP 地址。