计算机网络知识详解之:TCP连接原理详解

TCP连接

HTTP是上层应用层的网络传输协议定义了网络传输中的通信格式而实际的传输则由传输层的TCP/IP协议负责。HTTP 通信由 TCP/IP 承载的 TCP/IP 是全球计算机及网络设备都在使用的一种常用的分组交换网络分层协议集。 客户端应用程序可以打开一条 TCP/IP 连接连接到可能运行在世界任何地方的服务器应用程序。 一旦连接建立 在客户端和服务器的计算机之间交换的报文就永远不会丢失、 受损或失序。

在这里插入图片描述

三次握手

TCP协议目的是为了保证数据能在两端准确连续的流动可以想象两个建立起TCP通道的设备就如同接起了一根水管数据就是水管中的水由一头流向另一头。然而TCP为了能让一个设备连接多根“水管”让一个设备能同时与多个设备交互信息它必须要保证不同水管之间不会产生串联或相互影响

为了确保数据能够正确分发TCP用一种叫做TCB也叫传输控制块的数据结构把发给不同设备的数据封装起来我们可以把该结构看做是信封。一个TCB数据块包含了数据发送双方对应的socket信息以及拥有装载数据的缓冲区。

在两个设备要建立连接发送数据之前双方都必须要做一些准备工作分配内存建立起TCB数据块就是连接建立前必须要做的准备工作 。

在这里插入图片描述

一、准备工作

最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端被动打开连接的是服务器。

TCP服务器进程先创建传输控制块TCB时刻准备接受客户进程的连接请求此时服务器就进入了LISTEN监听状态

二、一次握手

TCP客户进程也是先创建传输控制块TCB然后向服务器发出连接请求报文这是报文首部中的同部位SYN=1同时选择一个初始序列号 seq=x

此时TCP客户端进程进入了 SYN-SENT同步已发送状态状态。TCP规定SYN报文段SYN=1的报文段不能携带数据但需要消耗掉一个序号。

三、二次握手

TCP服务器收到请求报文后如果同意连接则发出确认报文。确认报文中应该 ACK=1SYN=1确认号是ack=x+1同时也要为自己初始化一个序列号seq=y此时TCP服务器进程进入了SYN-RCVD同步收到状态。这个报文也不能携带数据但是同样要消耗一个序号。

ACK为1表示确认号有效为0表示报文中不包含确认信息  

四、三次握手

TCP客户进程收到确认后还要向服务器给出确认。确认报文的ACK=1ack=y+1自己的序列号seq=x+1此时TCP连接建立客户端进入ESTABLISHED已建立连接状态。TCP规定ACK报文段可以携带数据但是如果不携带数据则不消耗序号。

当服务器收到客户端的确认后也进入established状态此后双方就可以开始通信了。

注tcp建立连接需要三次握手SYN是发送标志位ACK是确认标志位.

为什么TCP客户端最后还要发送一次确认呢

主要防止已经失效的连接请求报文突然又传送到了服务器从而产生错误。

如果使用的是两次握手建立连接假设有这样一种场景客户端发送了第一个请求连接并且没有丢失只是因为在网络结点中滞留的时间太长了由于TCP的客户端迟迟没有收到确认报文以为服务器没有收到此时重新向服务器发送这条报文此后客户端和服务器经过两次握手完成连接传输数据然后关闭连接。此时此前滞留的那一次请求连接网络通畅了到达了服务器这个报文本该是失效的但是两次握手的机制将会让客户端和服务器再次建立连接这将导致不必要的错误和资源的浪费。

如果采用的是三次握手就算是那一次失效的报文传送过来了服务端接受到了那条失效报文并且回复了确认报文但是客户端不会再次发出确认。由于服务器收不到确认就知道客户端并没有请求连接。

为什么要3次握手?

换个易于理解的视角来看为什么要3次握手。

客户端和服务端通信前要进行连接3次握手的作用就是双方都能明确自己和对方的收、发能力是正常的。

第一次握手客户端发送网络包服务端收到了。这样服务端就能得出结论客户端的发送能力、服务端的接收能力是正常的。

第二次握手服务端发包客户端收到了。这样客户端就能得出结论服务端的接收、发送能力客户端的接收、发送能力是正常的。

  • 从客户端的视角来看我接到了服务端发送过来的响应数据包说明服务端接收到了我在第一次握手时发送的网络包并且成功发送了响应数据包这就说明服务端的接收、发送能力正常。
  • 而另一方面我收到了服务端的响应数据包说明我第一次发送的网络包成功到达服务端这样我自己的发送和接收能力也是正常的。

第三次握手客户端发包服务端收到了。这样服务端就能得出结论客户端的接收、发送能力服务端的发送、接收能力是正常的。 第一、二次握手后服务端并不知道客户端的接收能力以及自己的发送能力是否正常。而在第三次握手时服务端收到了客户端对第二次握手作的回应。从服务端的角度我在第二次握手时的响应数据发送出去了客户端接收到了。所以我的发送能力是正常的。而客户端的接收能力也是正常的

因此三次握手的主要目的就是收发双方为了确认彼此是否可以正常通信而进行的。只有能够正常通信才会后续发送请求报文。同时也是为了建立收发双发的确认号Ack和序号Seq的值在后续的数据传输阶段都是在彼此Ack和Seq值的基础上进行计算的这样做保证了TCP报文传输的连贯性

在这里插入图片描述

三次握手也是客户端和服务端建立通信连接的过程。

经历了上面的三次握手过程客户端和服务端都确认了自己的接收、发送能力是正常的。之后就可以正常通信了。

握手中的SYN超时重试

如果server端接到了clien发的SYN后回了SYN-ACK后client掉线了server端没有收到client回来的ACK那么这个连接处于一个中间状态即没成功也没失败。于是server端如果在一定时间内没有收到的TCP会重发SYN-ACK。在Linux下默认重试次数为5次重试的间隔时间从1s开始每次都翻售5次的重试时间间隔为1s, 2s, 4s, 8s, 16s总共31s第5次发出后还要等32s都知道第5次也超时了所以总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63sTCP才会把断开这个连接。

TCP协议缺陷

DDOS又称为分布式拒绝服务全称是Distributed Denial of Service。DDOS本是利用合理的请求造成服务器资源过载导致服务不可用。常见的DDOS攻击有SYN floodSYN flood、UDP flood、ICMP、flood等其中SYN flood是一种最为经典的DDOS攻击。SYN flood如此猖獗是因为它利用了TCP协议设计中的缺陷而TCP/IP协议是整个互联网的基础牵一发而动全身如今想要修复这样的缺陷几乎成为不可能的事情。

SYN flood攻击原理

  1. SYN flood在攻击时首先伪造大量的源IP地址分别向服务器端发送大量的SYN包
  2. 服务器端返回SYN/ACK包因为源地址是伪造的所以伪造的IP并不会应答
  3. 服务器端没有收到伪造IP的回应会重试3~5次并且等待一个SYN Time—般为30秒至2分钟如果超时则丢弃这个连接
  4. 攻击者大量发送这种伪造源地址的SYN请求服务器端将会消耗非常多的资源来处理这种半连接同时还要不断地对这些IP进行SYN+ACK重试。
  5. 最后的结果是服务器无暇理睬正常的连接请求导致拒绝服务。

四次挥手

原理

数据传输完毕后双方都可释放连接。最开始的时候客户端和服务器都是处于established表示连接已经建立状态然后客户端主动关闭服务器被动关闭。

在这里插入图片描述

  1. 客户端进程发出连接释放报文并且停止发送数据。释放数据报文首部FIN=1FIN表示关闭连接SYN表示建立连接其序列号为seq=u等于前面已经传送过来的数据的最后一个字节的序号加1此时客户端进入FIN-WAIT-1终止等待1状态。 TCP规定FIN报文段即使不携带数据也要消耗一个序号。

  2. 服务器收到连接释放报文发出确认报文ACK=1ack=u+1确认序号为收到的序号加1并且带上自己的序列号seq=v此时服务端就进入了CLOSE-WAIT关闭等待状态。TCP服务器通知高层的应用进程客户端向服务器的方向就释放了这时候处于半关闭状态即客户端已经没有数据要发送了但是服务器若发送数据客户端依然要接受。这个状态还要持续一段时间也就是整个CLOSE-WAIT状态持续的时间。

  3. 客户端收到服务器的确认请求后此时客户端就进入FIN-WAIT-2终止等待2状态等待服务器发送连接释放报文在这之前还需要接受服务器发送的最后的数据。

  4. 服务器将最后的数据发送完毕后就向客户端发送连接释放报文FIN=1ack=u+1由于在半关闭状态服务器很可能又发送了一些数据假定此时的序列号为seq=w此时服务器就进入了LAST-ACK最后确认状态等待客户端的确认。

  5. 客户端收到服务器的连接释放报文后必须发出确认ACK=1ack=w+1而自己的序列号是seq=u+1此时客户端就进入了TIME-WAIT时间等待状态。注意此时TCP连接还没有释放必须经过2*MSL最长报文段寿命的时间后当客户端撤销相应的TCB后才进入CLOSED状态。

  6. 服务器只要收到了客户端发出的确认立即进入CLOSED状态。同样撤销TCB后就结束了这次的TCP连接。可以看到服务器结束TCP连接的时间要比客户端早一些。

    FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时它想主动关闭连接向对方发送了FIN报文此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后则进入到FIN_WAIT_2状态

总结

  1. TCP客户端发送一个FIN用来关闭客户到服务器的数据传送。
  2. 服务器收到这个FIN它发回一个ACK确认序号为收到的序号加1。和SYN一样一个FIN将占用一个序号。
  3. 服务器关闭客户端的连接发送一个FIN给客户端。
  4. 客户端发回ACK报文确认并将确认序号设置为收到序号加1。

为什么客户端最后还要等待2MSL

MSLMaximum Segment LifetimeTCP允许不同的实现可以设置不同的MSL值。

去向ACK消息最大存活时间MSL) + 来向FIN消息的最大存活时间(MSL)。这恰恰就是**2MSL( Maximum Segment Life)。

第一保证客户端发送的最后一个ACK报文能够到达服务器因为这个ACK报文可能丢失站在服务器的角度看来我已经发送了FIN+ACK报文请求断开了客户端还没有给我回应应该是我发送的请求断开报文它没有收到于是服务器又会重新发送一次而客户端就能在这个2MSL时间段内收到这个重传的报文接着给出回应报文并且会重启2MSL计时器。

第二等待2MSL时间客户端就可以放心地释放TCP占用的资源、端口号。如果不等释放的端口可能会重连刚断开的服务器端口这样依然存活在网络里的老的TCP报文可能与新TCP连接报文冲突造成数据冲突为避免此种情况需要耐心等待网络老的TCP连接的活跃报文全部死翘翘2MSL时间可以满足这个需求尽管非常保守

为什么建立连接是三次握手关闭连接确是四次挥手呢

建立连接的时候 服务器在LISTEN状态下收到建立连接请求的SYN报文后把ACK和SYN放在一个报文里发送给客户端。

关闭连接时服务器收到对方的FIN报文时仅仅表示对方不再发送数据了但是还能接收数据而自己也未必已经将全部数据都发送给对方了所以己方可以立即关闭也可以发送一些数据给对方后再发送FIN报文给对方来表示同意现在关闭连接因此己方ACK和FIN一般都会分开发送从而导致多了一次

如果已经建立了连接但是客户端突然出现故障了怎么办

TCP还设有一个保活计时器显然客户端如果出现故障服务器不能一直等下去白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器时间通常是设置为2小时若两小时还没有收到客户端的任何数据服务器就会发送一个探测报文段以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应服务器就认为客户端出了故障接着就关闭连接。

TCP数据传输

传输原理

TCP通过 “ 发送 — 应答 ACK确认”来确保传输的可靠性它是端到端传输的。

TCP传输是分段的一个HTTP响应报文会被操作系统切成多个MSSMaximum Segment Size大小的段直到接收端接受到完整的报文为止。 在此过程中报文分段按照顺序进行发送每个报文段在发送时会做顺序编号以便能够完整正确地组装。

MSS:Maximum Segment Size 最大报文段长度,是TCP协议的一个选项用于在TCP连接建立时收发双方协商通信时每一个报文段所能承载的最大数据长度不包括文段头。如果MSS选项数据为512则表示该报文段的发送方可以处理的最大报文段长度为512字节不包括TCP与IP协议头长度。主机一般默认MSS为536字节

在这里插入图片描述

端口号

表示同一个计算机上的不同进程

源端口号和目标端口号都是占用了两个字节

TCP的源端口号和目标端口号预计IP报文中的源IP和目标IP确认一条唯一的TCP连接

序号

Seq4个字节

确认序号

Ack占四个字节

控制位

URG、ACK、PSH、RST、SYN、FIN

TCP 的数据是通过名为 IP 分组 或 IP 数据报 的小数据块来发送的。HTTP就是“HTTP over TCP over IP” 这个“协议栈” 中的最顶层了。 其安全版本 HTTPS就是在 HTTP 和 TCP 之间插入了一个 称为 TLS 或 SSL的 密码加密层。

HTTP 要传送一条报文时 会以流的形式将报文数据的内容通过一条打开的TCP 连接按序传输。 TCP 收到数据流之后 会将数据流砍成被称作段的小数据块 并将段封装在 IP 分组中 通过因特网进行传输。 所有这些工作都是由TCP/IP 软件来处理的 HTTP 程序员什么都看不到

每个 TCP 段都是由 IP 分组承载 从一个 IP 地址发送到另一个 IP 地址的。 每个 IP分组中都包括

  • 一个 IP 分组首部通常为 20 字节
  • 一个 TCP 段首部通常为 20 字节
  • 一个 TCP 数据块0 个或多个字节

IP 首部包含源和目的 IP 地址、 长度和其他一些标记。 TCP 段的首部包含了TCP端口号、 TCP 控制标记 以及用于数据排序和完整性检查的一些数字值。

在这里插入图片描述

TCP 连接是通过 4 个值来识别的
< 源 IP 地址、 源端口号、 目的 IP 地址、 目的端口号 >

这 4 个值一起唯一地定义了一条连接。 两条不同的 TCP 连接不能在同一时刻拥有 4 个完全相同的地址组件值

在这里插入图片描述

有些连接共享了相同的目的端口号C 和 D 都使用目的端口号 80。 有些连接使用了相同的源 IP 地址B 和 C。 有些使用了相同的目的 IP 地址A 和 BC和 D。 但没有两个不同连接所有的 4 个值都一样。

滑动窗口协议

将TCP与UDP这样的简单传输协议区分开来的两种协议不同的传输数据的质量。TCP对于发送数据进行跟踪这种数据管理需要协议有以下两大关键功能

  • 可靠性 保证数据确实到达目的地。如果未到达能够发现并重传。
  • 数据流控 管理数据的发送速率以使接收设备不致于过载

要完成这些任务整个协议操作是围绕滑动窗口确认机制来进行的。因此理解了滑动窗口也就是理解了TCP。

在我们滑动窗口协议之前我们如何来保证发送方与接收方之间每个包都能被收到并且是按次序的呢

在这里插入图片描述

问题

吞吐量非常的低。我们发完包1一定要等确认包1我们才能发送第二个包。

那么我们就不能先连发几个包等他一起确认吗这样的话速度更快吞吐量更高

在这里插入图片描述

问题

如果过多的源同时以很快的速度发送大量的数据包而此时接收方并没有如此高的接收数据的能力因此极易导致网络的拥塞。

滑动窗口协议Sliding Window Protocol

该协议是 TCP协议 的一种应用用于网络数据传输时的流量控制以避免拥塞的发生。**该协议允许发送方在停止并等待确认前发送多个数据分组。**由于发送方不必每发一个分组就停下来等待确认。因此该协议可以加速数据的传输提高网络吞吐量。滑动窗口算法其实和这个是一样的只是用的地方场景不一样。

如果我们在任一时间点对于这一过程做一个“快照”那么我们可以将TCP buffer中的数据分为以下四类并把它们看作一个时间轴

  1. 已发送已确认 数据流中最早的字节已经发送并得到确认。这些数据是站在发送设备的角度来看的。
  2. 已发送但尚未确认 已发送但尚未得到确认的字节。发送方在确认之前不认为这些数据已经被处理。
  3. 未发送而接收方已Ready 设备尚未将数据发出但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。
  4. 未发送而接收方Not Ready 由于接收方not ready还不允许将这部分数据发出。

在这里插入图片描述

说明

  • 灰色1号2号3号包已经发送完毕并且已经收到Ack。这些包就已经是过去式。
  • 4、5、6号包是黄色的表示已经发送了。但是并没有收到对方的Ack所以也不知道接收方有没有收到。
  • 7、8、9号包是淡蓝色的。是我们还没有发送的。这些淡蓝色也就是我们接下来马上要发送的包。
  • 后面的10-15还没有被读进内存。要等4号-9号包有接下来的动作后我们的包才会继续往下发送。

正常情况

在这里插入图片描述

可以看到4号包对方已经被接收到所以被涂成了灰色。“窗口”就往右移一格。我们就把11号包读进了我们的缓存。进入了“待发送”的状态。8、9号包已经变成了黄色表示已经发送出去了。接下来的操作就是一样的了确认包后窗口往后移继续将未发送的包读进缓存把“待发送“状态的包变为”已发送“。

丢包情况

有可能我们包5-11发过去对方的Ack丢了。也有可能我们的包并没有发送过去。从发送方角度看就是我们没有收到Ack。

在这里插入图片描述

发生的情况一直在等Ack。如果一直等不到的话我们也会把读进缓存的待发送的包也一起发过去。但是这个时候我们的窗口已经发满了。所以并不能把12号包读进来而是始终在等待5号包的Ack。

问题

如果我们这个Ack始终不来怎么办呢

超时重发/重传

原理是在发送某一个数据以后就开启一个计时器在一定时间内如果没有得到发送的数据报的ACK报文那么就重新发送数据直到发送成功为止。

影响超时重传机制协议效率的一个关键参数是重传超时时间RTORetransmission TimeOut。RTO的值被设置过大过小都会对协议造成不利影响。

  • RTO设长了重发就慢没有效率性能差。
  • RTO设短了重发的就快会增加网络拥塞导致更多的超时更多的超时导致更多的重发。
  • 连接往返时间RTTRound Trip Time指发送端从发送TCP包开始到接收它的立即响应所消耗的时间。

在 Unix 以及 Windows 系统中最初其重发超时的默认值一般设置为6秒重发时间必须是0.5秒的倍数左右。数据被重发之后若还是收不到确认应答则进行再次发送。此时等待确认应答的时间将会以2倍、4倍的指数函数延长。

此外数据也不会被无限、反复地重发。达到一定重发次数之后如果仍没有任何确认应答返回就会判断为网络或对端主机发生了异常强制关闭连接并且通知应用通信异常强行终止。

TCP性能

HTTP 紧挨着 TCP 位于其上层 所以 HTTP 事务的性能在很大程度上取决于底层TCP 通道的性能。

在这里插入图片描述

HTTP 事务的时延有以下几种主要原因

  1. 通过 DNS 解析系统将 URI 中的主机名转换成一个 IP地址要花费对应的时间
  2. 每条新的 TCP 连接都会有连接建立时延但如果有数百个 HTTP 事务的话 这个时间消耗值会快速地叠加上去。
  3. 网络传输请求报文及服务器处理请求报文都需要时间
  4. Web 服务器会回送 HTTP 响应的花费时间

这些网络时延的大小取决于硬件速度、 网络和服务器的负载 请求和响应报文的尺寸 以及客户端和服务器之间的距离。 TCP 协议的技术复杂性也会对时延产生巨大的影响

性能聚焦区域

  • TCP 连接建立握手
  • TCP 慢启动拥塞控制
  • TCP 延迟确认算法
  • Nagle 算法

TCP连接的握手时延

在这里插入图片描述

TCP 连接握手需要经过以下几个步骤。

  1. 请求新的 TCP 连接时 客户端要向服务器发送一个小的 TCP 分组通常是 40 ~60 个字节。 这个分组中设置了一个特殊的 SYN 标记 说明这是一个连接请求。
  2. 如果服务器接受了连接 就会对一些连接参数进行计算 并向客户端回送一个TCP 分组 这个分组中的 SYN 和 ACK 标记都被置位 说明连接请求已被接受
  3. 客户端向服务器回送一条确认信息 通知它连接已成功建立。现在的 TCP栈都允许客户端在这个确认分组中发送数据。

延迟确认(ACK)

由于网络自身无法确保可靠的分组传输 如果网络设备超负荷的话 可以随意丢弃分组 所以 TCP 实现了自己的确认机制来确保数据的成功传输。每个 TCP 段都有一个序列号和数据完整性校验和服务端收到完好的TCP段时都会向发送者回送小的确认报文。 如果发送者没有在指定的窗口时间内收到确认信息 发送者就认为分组已损毁或丢失 并重发数据。

由于确认报文很小 所以 TCP 允许在发往相同方向的输出数据分组中对其进行“捎带”。 TCP 将返回的确认信息与输出的数据分组结合在一起 可以更有效地利用网络。 为了增加确认报文找到同向传输数据分组的可能性 很多 TCP栈都实现了一种“延迟确认” 算法。 延迟确认算法会在一个特定的窗口时间 通常是 100 ~ 200 毫秒 内将输出确认存放在缓冲区中 以寻找能够捎带它的输出数据分组。 如果在那个时间段内没有输出数据分组 就将确认信息放在单独的分组中传送。

但是当希望有相反方向回传分组的时候 偏偏没有那么多。 通常 延迟确认算法会引入相当大的时延。

慢启动

慢启动算法思路

主机开发发送数据报时如果立即将大量的数据注入到网络中可能会出现网络的拥塞。慢启动算法就是在主机刚开始发送数据报的时候先探测一下网络的状况如果网络状况良好发送方每发送一次文段都能正确的接受确认报文段。那么就从小到大的增加拥塞窗口的大小即增加发送窗口的大小 用于防止因特网的突然过载和拥塞。

TCP 慢启动限制了一个 TCP 端点在任意时刻可以传输的分组数。 简单来说 每成功接收一个分组 发送端就有了发送另外两个分组的权限。 如果某个HTTP 事务有大量数据要发送 是不能一次将所有分组都发送出去的。 必须发送一个分组 等待确认 然后可以发送两个分组 每个分组都必须被确认这样就可以发送四个分组了以此类推。 这种方式被称为慢启动。

在这里插入图片描述

拥塞避免

由于上述慢启动方法中拥塞窗口的扩大方式采用指数型扩大因此在窗口大到一定程度后达到慢启动门限ssthresh减慢增加的速度转成线性扩大窗口的方式也就是每次收到新的 ACK 没有丢包的话只比上次窗口增大 1。整个过程看起来就像这样

在这里插入图片描述

超时重传和快速重传

随着窗口进一步缓慢增加终于有一天网络还是遇到了丢包的情况我们就会假定这是拥塞造成的。这个时候会进行超时重传或者快速重传

  • 超时重传往往拥塞情况严重采取策略也会更激进一些会直接将 ssthresh 设置为重传发生时窗口大小的一半而窗口大小直接重置为 0再进入慢启动阶段。

在这里插入图片描述

  • 快速重传 如果我们连续 3 次收到同样序号的 ACK包还能回传说明这个时候可能只是碰到了部分丢包网络阻塞还没有很严重此时就会采用柔和一点的策略也就是快速重传策略。我们会先把拥塞窗口变成原来的一半ssthresh 也就设置成当前的窗口大小然后开始执行拥塞避免算法。有些实现也会把拥塞窗口直接设置为 ssthresh+3本质上区别不大。

在这里插入图片描述

串行事务处理

如果只对连接进行简单的管理 TCP 的性能时延可能会叠加起来。 比如 假设有一 个包含了 3 个嵌入图片的 Web 页面。 浏览器需要发起 4 个 HTTP 事务来显示此页面1 个用于顶层的 HTML 页面 3 个用于嵌入的图片。 如果每个事务都需要串行地建立 一条新的连接 那么连接时延和慢启动时延就会叠加起来 。

在这里插入图片描述

除了串行加载引入的实际时延之外 加载一幅图片时 页面上其他地方都没有动静也会让人觉得速度很慢。 用户更希望能够同时加载多幅图片。

串行加载的另一个缺点是 有些浏览器在对象加载完毕之前无法获知对象的尺寸而且它们可能需要尺寸信息来决定将对象放在屏幕的什么位置上 所以在加载了足够多的对象之前 无法在屏幕上显示任何内容。 在这种情况下 可能浏览器串行装载对象的进度很正常 但用户面对的却是一个空白的屏幕 对装载的进度一无所知。

还有几种现存和新兴的方法可以提高 HTTP 的连接性能

  • 并行连接

    通过多条 TCP 连接发起并发的 HTTP 请求

  • 持久连接

    重用 TCP 连接 以消除连接及关闭时延

  • 管道化连接

    通过共享的 TCP 连接发起并发的 HTTP 请求

并行连接

如前所述 浏览器可以先完整地请求原始的 HTML 页面 然后请求第一个嵌入对象 然后请求第二个嵌入对象等 以这种简单的方式对每个嵌入式对象进行串行处理。 但这样实在是太慢了

HTTP 允许客户端浏览器打开多条TCP连接 并行地执行多个 HTTP 事务每个TCP连接处理一个HTTP事务。 在这个例子中 并行加载了四幅嵌入式图片 每个事务都有自己的 TCP 连接。 页面上的每个组件都包含一个独立的HTTP 事务

在这里插入图片描述

在这里插入图片描述

并行连接不一定更快

打开大量连接会消耗很多内存资源 从而引发自身的性能问题。 复杂的 Web页面可能会有数十或数百个内嵌对象。 客户端可能可以打开数百个连接 但 Web服务器通常要同时处理很多其他用户的请求 所以很少有 Web 服务器希望出现这样的情况。 一百个用户同时发出申请 每个用户打开 100 个连接 服务器就要负责处理10 000 个连接。 这会造成服务器性能的严重下降。 对高负荷的代理来说也同样如此。

实际上 浏览器确实使用了并行连接 但它们会将向同一个域名请求的并行连接的总数限制为一个较小的值。

浏览器同域名请求的最大并发数限制

在这里插入图片描述

持久连接

Web 客户端经常会打开到同一个站点的连接。 比如 一个 Web 页面上的大部分内嵌图片通常都来自同一个 Web 站点 而且相当一部分指向其他对象的超链通常都指向同一个站点。 因此 初始化了对某服务器 HTTP 请求的应用程序很可能会在不久的将来对那台服务器发起更多的请求比如 获取在线图片。这种性质被称为站点局部性site locality。

HTTP/1.1以及 HTTP/1.0 的各种增强版本 允许 HTTP 设备在事务处理结束之后将 TCP 连接保持在打开状态 以便为未来的 HTTP 请求重用现存的连接。在事务处理结束之后仍然保持在打开状态的 TCP 连接被称为持久连接。 非持久连接会在每个事务结束之后关闭。 持久连接会在不同事务之间保持打开状态直到客户端或服务器决定将其关闭为止。

重用已对目标服务器打开的空闲持久连接 就可以避开缓慢的连接建立阶段。而且已经打开的连接还可以避免慢启动的拥塞适应阶段 以便更快速地进行数据的传输。

Connection: Keep-Alive

在这里插入图片描述

在持久连接中每一个HTTP请求都是串行的。每个请求的发送都必须等待上一个请求的响应。

管道化连接

HTTP/1.1 允许在持久连接上使用管道化pipeline技术。 这是相对于 keepalive 连接的又一性能优化。

在响应到达之前 可以将多条请求放入队列。 当第一条请求通过网络流向另一端的服务器时 第二条和第三条请求也可以开始发送了。 在高时延网络条件下 这样做可以降低网络的环回时间 提高性能。

在这里插入图片描述

对管道化连接有几条限制

  • 必须按照与请求相同的顺序回送 HTTP 响应如果顺序发送了请求1/2/3那么无论服务器处理哪个请求更快相应的时候必须按照请求的顺序响应。 HTTP 报文中没有序列号标签 因此如果收到的响应失序了 就没办法将其与请求匹配起来了。此时容易引起一个问题头部阻塞。
  • HTTP 客户端必须做好连接会在任意时刻关闭的准备。 如果客户端打开了一条持久连接 并立即发出了 10 条请求服务器可能在只处理了5 条请求之后关闭连接剩下的 5 条请求会失败客户端必须能够应对这些过早关闭连接的情况 重新发出这些请求。
  • 只有幂等的请求能够被管线化。HTTP 客户端不应该用管道化的方式发送会产生副作用的请求比如 POST。 由于无法安全地重试 POST 这样的非幂等请求 所以出错时 就存在某些方法永远不会被执行的风险。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“计算机网络知识详解之:TCP连接原理详解” 的相关文章