TCP 三向握手时目的端口是否发生变化?

网络工程 通讯协议 协议理论 传输协议 第4层
2021-07-19 19:41:54

我正在学习 C 语言的网络编程,有一个问题让我很困扰,TCP 三向握手期间目标端口会改变吗?假设我有一个在端口 5000 上运行的 cilent 应用程序和一个在 tcp 端口 80 上运行的 Web 服务器。

我们知道 80 端口只是一个欢迎端口,当 Web 服务器收到一个 http 请求时,它会创建一个新的连接端口(比如说 5000)

所以我的理解是,客户端的初始地址用来发送数据包到服务器的IP地址+端口80,服务器(监听80端口)接受请求并创建一个新的连接端口(5000)后,然后后续客户端发送到 Web 服务器的数据包(包含数据有效负载)是服务器的 ip 地址 + 端口 5000。因此,如果您使用wireshark 捕获数据包,目标端口实际上从 80“更改”到 5000,您将看到两个端口,80 和 5000 作为TCP 标头中的目标端口,我的理解是否正确?

4个回答

不,TCP 连接由源和目标 IP 以及 TCP(端口)地址唯一标识。更改其中任何一项都会破坏 TCP 连接(或阻止它在握手中形成)。

您可能指的是 Web 浏览器将与 Web 服务器形成、使用和关闭多个 TCP 连接的事实。每个连接将使用不同的浏览器 TCP 源端口。


编辑,根据您的评论:

RFC 793,传输控制协议定义了 TCP,它解释了:

多路复用:

为了允许单个主机内的多个进程同时使用 TCP 通信设施,TCP 在每个主机内提供了一组地址或端口。与来自互联网通信层的网络和主机地址连接,形成一个套接字。一对套接字唯一标识每个连接。也就是说,一个套接字可以同时用于多个连接。

端口与进程的绑定由每个主机独立处理。然而,将经常使用的进程(例如,“记录器”或分时服务)附加到公知的固定套接字被证明是有用的。然后可以通过已知地址访问这些服务。建立和学习其他进程的端口地址可能涉及更多的动态机制。

连接:

上面描述的可靠性和流量控制机制要求 TCP 为每个数据流初始化和维护某些状态信息。这些信息(包括套接字、序列号和窗口大小)的组合称为连接。每个连接由一对标识其两侧的套接字唯一指定。

当两个进程希望通信时,它们的 TCP 必须首先建立连接(初始化每一方的状态信息)。当他们的通信完成时,连接被终止或关闭以释放资源以供其他用途。

由于必须在不可靠的主机和不可靠的互联网通信系统之间建立连接,因此使用基于时钟的序列号的握手机制来避免连接的错误初始化。

TCP 在进程/应用程序对等体之间创建双向连接(很像以太网在主机之间创建双向连接),并且每一方都可以使用该连接进行发送和接收。TCP 本身没有客户端或服务器,这是一个应用层概念。Web 浏览器将使用 TCP 连接向 Web 服务器发送请求,Web 服务器将使用相同的连接将请求的响应发送回 Web 浏览器。

Web 浏览器可以在同一 TCP 连接上发送多个请求并接收对请求的回复。有些网页浏览器为了同时请求不同的网页元素,会与网页服务器建立多个连接,但那是应用层的行为,不是TCP的行为,应用行为在这里是题外话。

服务器进程通常侦听一个众所周知的端口号,例如用于 HTTP 的 TCP 端口 80。客户端进程将请求 TCP 在服务器的已知端口号上创建到服务器进程的连接,并且通常使用保留端口,0以便 TCP 将为该连接分配客户端进程一个临时端口号当 TCP 连接终止时(任何一方都可以终止连接),临时端口将返回到临时端口号池,以供不同的连接重用。有些操作系统会以特定顺序使用可用池中的临时端口号,有些操作系统会为每个连接随机选择一个临时端口号。

RFC 中解释了连接的实际建立:

2.7 . 连接建立和清除

为了标识 TCP 可以处理的单独数据流,TCP 提供了端口标识符。由于端口标识符由每个 TCP 独立选择,因此它们可能不是唯一的。为了在每个 TCP 内提供唯一地址,我们将标识 TCP 的 Internet 地址与端口标识符连接起来,以创建一个套接字,该套接字在所有连接在一起的网络中都是唯一的。

连接完全由末端的一对套接字指定。本地套接字可能参与到不同外部套接字的许多连接。一个连接可以用来在两个方向上承载数据,即“全双工”。

TCP 可以随意将端口与进程相关联。然而,在任何实现中,几个基本概念都是必要的。必须有众所周知的套接字,TCP 仅通过某种方式将这些套接字与“适当的”进程相关联。我们设想进程可以“拥有”端口,并且进程只能在它们拥有的端口上发起连接。(实现所有权的方法是一个本地问题,但我们设想了一个请求端口用户命令,或者一种将一组端口唯一分配给给定进程的方法,例如,通过将端口名称的高位与给定进程相关联.)

连接在 OPEN 调用中由本地端口和外部套接字参数指定。作为回报,TCP 提供一个(短)本地连接名称,用户通过该名称在后续调用中引用该连接。关于连接,有几件事必须记住。为了存储这些信息,我们假设有一个称为传输控制块 (TCB) 的数据结构。一种实现策略将本地连接名称作为指向此连接的 TCB 的指针。OPEN 调用还指定是主动进行连接建立还是被动等待连接建立。

被动 OPEN 请求意味着该进程希望接受传入的连接请求,而不是尝试启动连接。通常,请求被动 OPEN 的进程会接受来自任何调用者的连接请求。在这种情况下,全零的外部套接字用于表示未指定的套接字。未指定的外部套接字仅允许在被动 OPEN 上使用。

希望为未知的其他进程提供服务的服务进程将使用未指定的外部套接字发出被动的 OPEN 请求。然后可以与任何请求连接到该本地套接字的进程建立连接。如果已知此本地套接字与此服务相关联,将会有所帮助。

众所周知的套接字是先验地将套接字地址与标准服务相关联的便利机制。例如,“Telnet-Server”进程永久分配给特定的套接字,而其他套接字则保留用于文件传输、远程作业输入、文本生成器、Echoer 和 Sink 进程(最后三个用于测试目的)。套接字地址可能会保留用于访问“查找”服务,该服务将返回提供新创建服务的特定套接字。众所周知的套接字的概念是 TCP 规范的一部分,但将套接字分配给服务不在此规范之内。(见 [4]。)

进程可以发出被动 OPEN 并等待来自其他进程的匹配主动 OPEN,并在建立连接时由 TCP 通知。同时向彼此发出主动 OPEN 的两个进程将被正确连接。这种灵活性对于支持分布式计算至关重要,在分布式计算中,组件彼此之间异步操作。

匹配本地被动OPEN和外部主动OPEN中的socket有两种主要情况。在第一种情况下,本地被动 OPEN 已完全指定外部套接字。在这种情况下,匹配必须是精确的。在第二种情况下,本地被动 OPEN 未指定外部套接字。在这种情况下,只要本地套接字匹配,任何外部套接字都是可以接受的。其他可能性包括部分受限的匹配。

如果有多个挂起的被动 OPEN(记录在 TCB 中)具有相同的本地套接字,则在选择具有外部主动 OPEN 的特定外部套接字的 TCB 之前,外部主动 OPEN 将匹配未指定的外部套接字。

建立连接的过程利用同步 (SYN) 控制标志并涉及三个消息的交换。这种交换被称为三向握手 [3]。

连接由到达段的集合发起,该段包含一个 SYN 和一个等待的 TCB 条目,每个条目都由用户 OPEN 命令创建。本地和外部套接字的匹配决定了何时发起连接。当序列号在两个方向上同步时,连接就“建立”了。

连接的清除还涉及段的交换,在这种情况下携带 FIN 控制标志。

我们知道 80 端口只是一个欢迎端口,当 Web 服务器收到一个 http 请求时,它会创建一个新的连接端口(比如说 5000)

这对于 HTTP 协议来说是不正确的。一些协议,即 FTP,与此类似,但不是 HTTP。

所以我的理解是,客户端的初始地址用来发送数据包到服务器的IP地址+端口80,服务器(监听80端口)接受请求并创建一个新的连接端口(5000)后,然后后续客户端发送到 Web 服务器的数据包(包含数据负载)是服务器的 IP 地址 + 端口 5000

不适用于 HTTP(如您所说的“网络服务器”)

对于 HTTP,流量流看起来像:

  1. 客户端选择一个临时端口例如,假设选择了 12345
  2. 客户端发送一个SYN设置标志的数据包,源端口为 12345,目标 IP 为服务器地址,目标端口为 80
  3. 服务器接收到数据包,并发送一个带有SYN,ACK标志设置的数据包,目标是第一个数据包的源 IP 和端口(目标端口 12345)和端口 80
  4. 客户端收到数据包,发回一个ACK设置标志的数据包(再次使用源端口 12345 和目标端口 80)
  5. 连接现已打开。客户端发送数据包(源端口 12345,目标端口 80)与 HTTP 请求(GET / HTTP/1.1...或类似)
  6. 服务器处理请求并返回响应,方式相同(源端口80,目标端口12345)

因为这是 HTTP,所以很可能正在传输 HTML,这将触发额外的 HTTP 请求以获取资产(图像、CSS、javascript 等)。这些额外的 HTTP 请求看起来与上面的完全一样,只是临时端口(12345) 会有所不同,但服务器的源端口将始终为 80。


现在,如果您询问使用两个端口不同协议,即FTP,通信流程将类似于:

  1. 客户端选择一个临时端口例如,假设选择了 12345
  2. 客户端发送一个SYN设置标志的数据包,源端口为 12345,目标 IP 为服务器地址,目标端口为 21
  3. 服务器接收数据包,并发送一个带有SYN,ACK标志的数据包,其中的目标是第一个数据包的源 IP 和端口(目标端口 12345),端口为 21
  4. 客户端收到数据包,发回一个ACK设置标志的数据包(再次使用源端口 12345 和目标端口 21)
  5. 控制连接现已开放。客户端发送一个包含 FTP 请求的数据包(源端口 12345,目标端口 21)。
  6. 当需要传输数据时,服务器(或客户端,取决于 PASV 模式...)为该通道选择一个 -second_ 端口,然后在该端口上发生第二个三向握手。SYN从运动 23456 到目标端口 5000,SYNACK回到 dport 23456,ACK回到 5000)
  7. 现在,您有两个 TCP 连接;一个用于命令(“发送此文件的数据,停止,更改目录...”),第二个用于实际数据流

但即使在这种情况下,目标端口在 TCP 三向握手期间也不会改变——有两个单独的三向握手。

我们知道 80 端口只是一个欢迎端口,当 Web 服务器收到一个 http 请求时,它会创建一个新的连接端口(比如说 5000)

这似乎是你误解的根源。这是不准确的。所述客户机选取一个随机高数端口作为建立连接时端口。这发生在发送 TCP SYN 数据包之前,因此在握手期间它不会改变。在 TCP 连接的整个生命周期中,目标端口保持端口 80。目标端口唯一不同的情况是,如果您在具有相同 IP 地址的同一主机上运行多个 Web 服务器,在这种情况下,与主机上每个单独 Web 服务器的所有连接仍将连接到单个端口,但不同的服务器将在不同的端口号上运行。

TCP 连接由 4 个值唯一标识:源 IP 地址、目标 IP 地址、源端口号和目标端口号。不需要每个客户端的目的端口号都不同,因为源 IP 地址和端口号将唯一标识每个客户端的连接,因此服务器的操作系统知道将每个数据包传送到 web 中的哪个 TCP 套接字服务器(或任何类型的服务器。)

只要每个客户端都有唯一的源 IP 地址和端口地址组合,给定的主机就可以支持任意数量的客户端同时连接到同一个 TCP 端口。

不 ,!服务器目标端口永远不会改变它在您的场景中保持不变,它是 http 端口 80 。应用程序托管在端口 80 上,服务在目标服务器的端口 80 上侦听。

当客户端请求访问端口 80 上的网络服务器时,客户端将根据您的示例生成一个源端口,它是端口 5000,目标端口是端口 80,端口 5000 用作反向到目标流量的参考,以正确启动流量的主机。