计算机网络 TCP 协议总结

简介: TCP/IP 协议占据了互联网通信的一大半江山,特别像 TCP 这种保障端到端的可靠传输更是相当重要,关于它的实现也很复杂,今天介绍下关于 TCP 的相关重要知识。

TCP 相关知识

TCP/IP 协议占据了互联网通信的一大半江山,特别像 TCP 这种保障端到端的可靠传输更是相当重要,关于它的实现也很复杂,今天介绍下关于 TCP 的相关重要知识。

我们先来看下 TCP 的头格式:

TCP 头部

我们看到有一个源端口目的端口,这 2 个元素再加上 IP 层的源地址目的地址,就可以用来表示 TCP 的某个连接了,相当于数据库里的唯一标识。所以当我们发起一个 TCP 连接时,会发现如果存在相同的端口在运行时,操作系统是不允许的,只有这样才能保证唯一连接的存在,避免数据接收混乱。

在上图中,我们会看到以下几个元素,它们是 TCP 协议对几个重要问题的保障:

  • 序列号(seq):数据包的序号,通过序号来确认包的连续性,解决包的乱序问题。
  • 响应号(ack):针对上面字段的确认序号,比如服务器接收到客户端的请求,里面包含了 seq 序号,此时服务器响应回去时,会进行 ack = seq + 1 的字段设置,表示已接收到的累积数据。
  • Window:滑动窗口使用,用来反馈接收方接下来能处理的包大小,防止双方对数据包的处理能力不对等,主要解决了流控问题。
  • TCP Flag:TCP 包的类型,用来辅助 TCP 的阶段处理,比如 SYN 表示建立连接,FIN 表示关闭连接。

TCP 状态流转

协议之所以会存在,就在于双方需要互相配合协作,以确定哪个阶段该做哪些事情。在 TCP 协议总体划分为建立连接数据传输连接断开这三个过程。这些阶段将会涉及对应状态的流转:

状态机 (图片地址)

TCP 的三次握手、四次挥手

而在上面的状态流转中,最重要,也是经常会提起的关于连接建立的三次握手以及连接断开的四次挥手
三次握手、四次挥手

从上面的流程图中,我们会发现对于 Client 端来讲,经历了一个请求-确认过程;对于 Server 端来讲,也经历了一个请求-确认过程。这就相当于双方都已经互相确认过眼神了。所以,三次握手对于连接的建立是刚刚好的。

如果我们只进行 2 次握手就建立连接,那么对于 Server 端来讲太容易建立起连接了,基本是有客户端过来,那么 Server 就要建立起连接了。这种情况就会导致连接成本太低,Server 端很容超负载。

至于在关闭连接时需要四次挥手,主要是因为 TCP 是全双工的,存在了两个方向的数据发送与接收,所以需要在两个方向都进行关闭流程。否则一方关闭了,另一方还在傻傻等待,只能等待异常超时结束了。

TIME_WAIT

在四次挥手中,有一个状态是 TIME_WAIT,它是主动关闭者在最后会进行的动作,是一个定时设置,在 2*MSL(MSL 表示一个包在网络环境中的生存时间,一般为 2 分钟, Linux 里为 30s)时间过后就会真正的 CLOSED。

之所以不立即关闭,主要为了让被动关闭方能有足够的时间接收到最后的 Ack 包,如果没有接收到,被动方就会重新发送 Fin 包,重新触发主动方发送最后的 Ack 包。这样的话,就能尽量保证被动关闭方尽快关闭连接了,毕竟主动关闭方需要承担起主要责任,所以会有 TIME_WAIT 的等待了。

另外一个原因也是怕当前连接立马释放,有一定概率会立马被使用到,就有可能产生包的混乱问题了。

TCP 重传

TCP 发送的包都需要接收方进行一个 Ack 包的响应,如果在一定时间内没有响应的话,那么发送方就会认为包未能正确到达,需要进行重传动作。这就是 TCP 的重传机制。

TCP 里的重传机制会有一个超时的判断,这个超时时间并不是很准确,或者说并不是很标准,毕竟不同的网络环境,包的到达情况都会是不一样的。

所以 TCP 会使用一个采样时间,先记录了正常情况下一个数据包从发送到响应确认这么一来一回的时间,即所谓的 RTT(Round Trip Time) 时间,根据这个时间进行一些公式计算,得到了超时时间的值:RTO(Retransmission TimeOut)

对于重传机制,还有另外一种触发机制。上面的情况属于发送方去探知发送情况,也有另一种情况是接收方能探知的。比如发送方发送了 1, 2, 3 的包,但实际上接收方只接收到 1 和 3,一直没能收到 2 这个包,那此时接收方就会连续响应三个 关于 2 的 ack 包。

当发送方收到这么一个连续的 3 个 ack 包后,就知道需要重传 2 了,此时就不需要等到 2 的超时未确认触发,可以提前的重传 2 这个包了。

TCP 滑动窗口

重传机制使得数据包能够可靠的传输,然而如果接收方数据处理能力有限,而发送方未能感应到这种情况,不停的发送数据包,则会增加接收方的压力,还会导致网络拥塞的发生。

为此,TCP 采用滑动窗口进行了流量的控制,所谓的滑动窗口即在发送方和接收方各自维护了一个窗口,在这个窗口里将会维护对应的数据包,以感知当前的数据处理情况。

在接收方这边的窗口称之为接收窗口,它具体表示当前所能接收的数据包大小,计算公式为:当前最大可接收缓冲区大小 - 当前已接收的大小,在连接建好的开始一般为 65535 字节。

在计算出可接收大小后,接收方就会将此值设置在 TCP 头部里的 Window 字段,然后响应回发送方,发送方也就知道了当前所能允许发送的数据包大小了。

在发送方这边的窗口称之为发送窗口,按正常逻辑来讲,发送窗口维护的是即将要发送的数据,即根据刚刚反馈回来的接收窗口大小计算出的发送数据。

但由于一个数据包的发送需要有一个 ACK 响应才算完整流程,所以对于这些“已发送未响应”的数据也应该纳入到发送窗口的管理,并且只有真的 ACK 响应回来,才能继续下个数据包的准备发送。

[图片地址](https://ucc.alicdn.com/images/user-upload-01/img_convert/cb724c4210ceb584d1a7fdde7a4d21c7.png#pic_center)

需要注意的是,如果发送方接收到的 Window 大小为 0,则表示当前的接收方已经无能力处理新的包了,此时发送方就不会再下发数据了,直到接收方发送一个窗口通告,才继续数据的发送。

但此时需要考虑一种情况,就是接收方由于网络问题没能将窗口通告送达发送方,那此时发送方就会一直干等着了.所以对于发送方来讲,会启动窗口探知动作,让接收方 ACK 它当前的接收窗口大小,如果超过 3 次的探知动作,则直接断开连接了。

TCP 的拥塞控制

在一个复杂的网络环境中,数据包的传输不仅仅只涉及到端到端的,还可能会出现很多网络问题,导致包的堆积,影响了整体的传输速度。所以,TCP 协议需要将网络的阻塞情况考虑进来,避免加剧。这就是 TCP 的拥塞控制。

为此,TCP 协议抽象出了拥塞窗口(cwnd)的概念,它会根据当前的网络拥塞程度进行动态的调整。由于加入了拥塞情况的考虑,前面我们提到过的发送窗口则不能仅仅只考虑接收窗口这个因素了,需要进行 min(拥塞窗口,接收窗口)的选择了。

由此可见,拥塞窗口的计算很重要,它将决定了数据包的发送大小。而关于拥塞窗口的计算,它将在几个场景里会涉及到,下面我们一一来分析。

MTU 和 MSS

在分析拥塞窗口的具体场景之前,我们先来看看拥塞窗口的基本单位:MSS。MSS 表示 网络传输数据的最大值,如果 MSS 加上包头大小,则表示网络传输最大报文:MTU 了。

在 Internet 这种互联网中,一般 MTU 定义为 576 字节,减去 TCP、IP 的包头 40 字节,则可以得到 MSS = 536 字节的值;而在以太网这种局域网里,一般 MTU 会大点:1500 字节,MSS 为 1460 字节。

慢启动

当连接建立完毕,开始传输数据时,TCP 协议规定不能一开始就发送大尺寸的数据包,这样避免了网络环境有问题时,新加入的连接加剧了拥塞状况。所以,对于新加入的连接而言,需要一点一点的增大数据量,这就是所谓的慢启动

其中,慢启动涉及的拥塞窗口计算过程如下:

  • 刚开始建立好连接时,拥塞窗口 = 1
  • 每当接收到一个 ACK 包时,拥塞窗口 = 拥塞窗口 + 1,此时呈线性增加。
  • 每当经过一个 RTT,拥塞窗口 = 拥塞窗口 * 2,此时呈指数上升趋势。

拥塞避免

从慢启动的算法来看,每经过一个 RTT 后,拥塞窗口 的增长速度将会变得很厉害,如果没有进行限制的话,那么很快就会占满带宽了。因此, TCP 协议使用了一个叫慢启动门限(ssthresh)的变量(一般取 65535 字节)。当 cwnd 超过该限制后,就会进入所谓的拥塞避免阶段了。

在拥塞避免阶段,拥塞窗口的计算过程如下:

  • 每接收到一个 ACK 包时,拥塞窗口 = 拥塞窗口 + 1/拥塞窗口
  • 每当经过一个 RTT,拥塞窗口 = 拥塞窗口 + 1

从上面的算法可以看出,进入拥塞避免阶段后,数据包的发送大小将呈线性增加了。通过这样的方式,使得 TCP 的传输在前期很快,然后再慢慢降下来,达到网络最佳值。

拥塞发生

前面都是在避免拥塞的发生去动态调整拥塞窗口(cwnd)的,然而按照线性增长的趋势,始终会导致网络拥塞的。当发送拥塞(一般只要丢包,需要重传数据包就认为发送了拥塞)时,TCP 协议该如何处理呢?此处也算是 TCP 协议比较复杂的地方,因为它在不断的改进,也衍生出了很多版本,下面我们来看看这些不同版本的区别和处理吧。

Tahoe 版本

Tahoe 版本是 TCP 的最早版本,当它发现需要进行重传动作,即触发了 RTO 超时或发送方收到三个重复 ACK 包时,此时会进行的动作为:

  • sshthresh = cwnd /2
  • cwnd 重置为 1
  • 重回慢启动阶段

Reno 版本

Reno 版本进行的动作为:

  • sshthresh = cwnd /2
  • cwnd = sshthresh + 3 * MSS (将 3 个重复 ACK 考虑进去)
  • 进入快速恢复阶段

其中,快速恢复阶段的步骤如下:

  • 当重传的包发出去后,收到了重传包的 ACK 后,cwnd = cwnd + 1
  • 当收到新的数据包的 ACK 后,此时快速恢复过程已结束,则 cwnd = sshthresh,然后重回拥塞避免阶段

NewReno 版本

NewReno 是对 Reno 的改进,主要是优化了快速恢复阶段,在 Reno 版本中,所考虑的都是一个包的丢失情况。然而,在实际情况中,一次数据窗口的发送,是有可能出现很多数据包丢失情况的。

这样的话,就会触发多次的 cwnd 和 ssthresh 减半动作,一旦 cwnd 降到小于 3 时,即发送窗口会出现小于 3 的情形,此时将再也触发不了 3 次快速重传动作了,只能依赖 RTO 超时,而一般 RTO 的值是比较大(太小会经常触发重传)的,此时整个传输速度将会大大降低。

所以 NewReno 会在收到所有数据包的确认后才结束快速恢复阶段,这样 cwnd 和 sshthresh 就不会轻易被降低了。

NewReno 主要是使用了一个 recover 变量,作为当前数据窗口中,可能丢包的最大序号。即如果有丢包情况产生,并且大于当前的 recover 值,则会更新该值。

当收到接收方的 ack 后,会进行 ack_seq 的判断,如果 ack_seq > recover,此时就可以结束快速恢复阶段了;如果 ack_seq < recover,则意味着多包丢失,还不能结束快速恢复阶段。通过这样的控制,来提高了整个的吞吐量。

Nagle 算法

下面我们来看看 TCP 里的其他经典算法:Nagle。Nagle 算法是一种通过减少小数据包的发送来提高 TCP 效率的机制。它会把多个小数据包合并到一个片段,并且等待满足一定条件后,再一起发送过去。具体的触发条件是:

  • 如果包长度达到 MSS,则允许发送
  • 如果包含 FIN,则允许发送
  • 如果设置了 TCP_NODELAY,则允许发送
  • 未设置 TCP_CORK 选项时,若所有发出去的小数据包(包长度小于 MSS)均被确认,则允许发送

当上述条件都未满足,但发生了超时(一般为 200ms),则立即发送。

对于 TCP 协议来讲,默认会启用 Nagle 算法,降低网络负载,减少网络拥塞,提高网络吞吐。

Delay Ack

Delay Ack 指延迟发送 Ack。在 TCP 的确认机制里,可以在通信过程中不对每一个 TCP 数据包进行单独的 ACK 包响应,而是在传输数据时,顺便把 ACK 信息随数据包一起发送,这样可以提高利用率。

如果在一定时间内(一般 40 ms)没有数据包要发送,那么就会单独的进行 ACK 包响应。这个过程就被称为 Delay Ack 了。

粘包与拆包

TCP 是面向字节流的传输,它会根据接收方的包处理能力以及当前网络的拥塞情况来一部分一部分的加载数据发送,再加上有 Nagle 这种整合小数据包的算法存在。所以对于接收方来讲,接收到的数据有可能是粘合在一起的,也有可能是被拆分开的,即所谓的粘包和拆包。

对于粘包和拆包现象,常用的解决方案有:

  • 在包的首部添加当前要传输的数据包的长度,让接收方根据长度去切割。
  • 将数据包封装为固定长度,不够的补 0,让接收方按固定长度解析。
  • 人为的给数据包添加边界,比如在数据包结尾添加特殊字符,当解析到特殊字符时,接收方就认为读取到了一个完整有意义的数据段了。
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
负载均衡 网络协议 算法
|
4天前
|
负载均衡 网络协议 算法
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
这网络层就像搭积木一样,上层协议都是基于下层协议搭出来的。不管是ping(用了ICMP协议)还是tcp本质上都是基于网络层IP协议的数据包,而到了物理层,都是二进制01串,都走网卡发出去了。 如果网络环境没发生变化,目的地又一样,那按道理说他们走的网络路径应该是一样的,什么情况下会不同呢? 我们就从路由这个话题聊起吧。
22 4
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
|
26天前
|
安全 搜索推荐 网络安全
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
53 11
|
25天前
|
监控 网络协议 网络性能优化
网络通信的核心选择:TCP与UDP协议深度解析
在网络通信领域,TCP(传输控制协议)和UDP(用户数据报协议)是两种基础且截然不同的传输层协议。它们各自的特点和适用场景对于网络工程师和开发者来说至关重要。本文将深入探讨TCP和UDP的核心区别,并分析它们在实际应用中的选择依据。
53 3
|
1月前
|
网络协议 网络安全 网络虚拟化
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算。通过这些术语的详细解释,帮助读者更好地理解和应用网络技术,应对数字化时代的挑战和机遇。
90 3
|
1月前
|
网络虚拟化
生成树协议(STP)及其演进版本RSTP和MSTP,旨在解决网络中的环路问题,提高网络的可靠性和稳定性
生成树协议(STP)及其演进版本RSTP和MSTP,旨在解决网络中的环路问题,提高网络的可靠性和稳定性。本文介绍了这三种协议的原理、特点及区别,并提供了思科和华为设备的命令示例,帮助读者更好地理解和应用这些协议。
57 4
|
1月前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
52 13
|
1月前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
1月前
|
网络协议 算法 网络性能优化
计算机网络常见面试题(一):TCP/IP五层模型、TCP三次握手、四次挥手,TCP传输可靠性保障、ARQ协议
计算机网络常见面试题(一):TCP/IP五层模型、应用层常见的协议、TCP与UDP的区别,TCP三次握手、四次挥手,TCP传输可靠性保障、ARQ协议、ARP协议
|
7天前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
45 17