HTTP POST 是否需要 TCP 三向握手?

网络工程 ip 通讯协议 协议理论 第4层 传输协议
2021-08-01 18:03:35

我不太明白我是否将 http 表单数据从浏览器发布到服务器,该协议是否仍然需要进行三向握手(syn-ack-data)还是仅适用于 GET http 请求?

3个回答

如果你问的是一般意义上的问题,那么答案肯定是“是”,任何 HTTP 方法(如 POST)都需要 TCP 连接,而发起 TCP 连接的唯一方法是使用三向握手。

但是,如果您在特定情况下询问,也许如果您正在捕获自己的流量并且在向网站提交内容后没有看到 3 次握手,那么答案就不那么简单了。我们必须先讨论一些与 HTTP 相关的概念,然后才能正确地回答它……


在 HTTP1.0 的原始版本中,您从网页请求的每个对象都需要为每个对象形成一个新的 TCP 连接。以以下简单的网站为例,其中包含一些文本和两张图片:

<HTML>
  <HEAD>
    <TITLE>My Title</TITLE>
  </HEAD>
  <BODY>
    Stack Exchange Rules!
    <IMG SRC="a.gif">
    <IMG SRC="b.gif">
  </BODY>
</HTML>

在传统的 HTTP1.0 中,将此网站加载到您的浏览器需要三个 TCP 连接(每个连接都有自己的 3 次握手和 4 次关闭)。

HTTP 1.0:

--> SYN
                SYN ACK <--
--> ACK

--> GET /index.html
           <index.html> <--

--> FIN
                    ACK <--
                    FIN <--
--> ACK

.

--> SYN
                SYN ACK <--
--> ACK

--> GET /a.gif
                <a.gif> <--

--> FIN
                    ACK <--
                    FIN <--
--> ACK

.

--> SYN
                SYN ACK <--
--> ACK

--> GET /b.gif
                <b.gif> <--

--> FIN
                    ACK <--
                    FIN <--
--> ACK

注意上面有27个包,只下载三个:HTML页面本身(index.html),image a.gif,image b.gif。 (实际上会有超过 27 个数据包,但为了节省垂直空间,我只在 3 路握手和 4 路关闭中包含了 ACK,并在数据流中省略了 ACK)

为了提高 HTTP 的效率,引入了一个叫做“Connection Keepalive”的特性,它允许 HTTP 重新使用同一个 TCP 连接来请求多个对象。上述转让将减少为以下内容:

带有连接保持连接的 HTTP 1.1

--> SYN
                SYN ACK <--
--> ACK

--> GET /index.html
           <index.html> <--
--> GET /a.gif
                <a.gif> <--
--> GET /b.gif
                <b.gif> <--

--> FIN
                    ACK <--
                    FIN <--
--> ACK

请注意,只有一个 TCP 连接用于请求所有三个对象。这次只用了 13 个数据包,比之前的 27 个有了很大的改进。

我们必须讨论的对 HTTP 的最后一项改进是称为流水线的功能。此功能进一步提高了 HTTP 的效率,使客户端可以一次请求多个选项,而无需等待接收先前请求的对象。我来给你展示:

带流水线的 HTTP1.1

--> SYN
                SYN ACK <--
--> ACK

--> GET /index.html
--> GET /a.gif
--> GET /b.gif
           <index.html> <--
                <a.gif> <--
                <b.gif> <--

--> FIN
                    ACK <--
                    FIN <--
--> ACK

我们仍然只使用一个 TCP 连接,我们仍然只使用 9 个数据包。但是,在请求和接收每个对象之间,我们不必等待客户端和服务器之间的往返时间 (RTT)。如果你需要一个类比,想象你在一家餐馆,你需要盐、胡椒和番茄酱。一次向服务员/女服务员询问所有三样东西,还是一次问一个并等待他们回来再提出下一个请求,是否更有效?

(流水线与您的问题没有直接关系,但通常与 Keepalives 和其他 HTTP 效率功能一起描述,因此为了完整起见,我决定将其包含在此答案中)


现在我们终于可以回到你的问题了:

HTTP POST 是否需要 TCP 三向握手?

如果您打开与 Web 服务器的连接并使用 GET 方法下载网页,并且该 Web 服务器支持连接保持连接。对该 Web 服务器的后续请求(包括 POST 方法)可能会简单地重新使用已经存在的 TCP 连接。因此,该特定 POST 不需要新的 3 次握手,因为数据将在现有 TCP 连接中传输。

然而,连接 Keepalive 没有无限的持续时间。因此,如果下载完网页后,您等待一段时间后才发送 POST,则原始 TCP 连接可能已经关闭,在这种情况下,您的浏览器将不得不打开一个新的 TCP 连接来 POST 数据,这显然需要启动与 3 次握手。

由于许多浏览器和网络服务器使用不同的计时器来确定他们希望“连接保持活动”功能保持连接活动多长时间,因此我无法为您提供有关它们通常持续多长时间的可靠数字。

HTTP GET 和 HTTP POSTS 都使用 TCP。如果您问 POST 是否还需要 3 次 TCP 握手 (syn-synack-ack),它就像任何其他 TCP 连接一样。在任何应用程序协议(例如 HTTP)开始工作之前,都需要 TCP 握手。

仅供参考,您的三向握手不正确;它应该是“syn-synack-ack”

添加:

如果浏览器使用QUIC(Quick UDP Internet Connections,发音为 quick。由 Google 提出)HTTP 协议,则可以避免 3 路 TCP 握手。但 AFAIK 它在 Chrome 和 Google 中支持。

大多数软件更喜欢HTTP/2,它仍然是 TCP,但具有许多功能,它使用持久连接,然后为每个服务器服务器完成一次 3 次握手。

如果使用此协议,任何请求都可以避免 3 路 hanshake,包括 GET。

的确。但无论如何,仍然有一种方法可以提高效率——数据可以放入 SYN-SYNACK-ACK 数据包中,尽管在握手完成之前,数据无法使用。