计算机网络 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,让接收方按固定长度解析。
  • 人为的给数据包添加边界,比如在数据包结尾添加特殊字符,当解析到特殊字符时,接收方就认为读取到了一个完整有意义的数据段了。
相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
数据采集 算法 数据挖掘
模块化控制协议(MCP)在网络中增强智能体执行效率的研究
随着Web3技术的迅速发展,去中心化应用和智能体在各种领域的应用逐渐增多。MCP(Modularized Control Protocol,模块化控制协议)作为一种增强智能体执行能力的关键技术,为Web3场景中的智能体提供了更强的灵活性和可扩展性。本文将探讨如何利用MCP技术提升智能体在Web3场景中的执行能力,并通过实例代码展示其实现路径。
375 22
|
1月前
|
监控 负载均衡 安全
WebSocket网络编程深度实践:从协议原理到生产级应用
蒋星熠Jaxonic,技术宇宙中的星际旅人,以代码为舟、算法为帆,探索实时通信的无限可能。本文深入解析WebSocket协议原理、工程实践与架构设计,涵盖握手机制、心跳保活、集群部署、安全防护等核心内容,结合代码示例与架构图,助你构建稳定高效的实时应用,在二进制星河中谱写极客诗篇。
WebSocket网络编程深度实践:从协议原理到生产级应用
|
2月前
|
运维 架构师 安全
二层协议透明传输:让跨域二层协议“无感穿越”多服务商网络
简介:本文详解二层协议透明传输技术,适用于企业网工、运营商及架构师,解决LLDP/LACP/BPDU跨运营商传输难题,实现端到端协议透传,提升网络韧性与运维效率。
|
6月前
|
安全 网络协议 Linux
Linux网络应用层协议展示:HTTP与HTTPS
此外,必须注意,从HTTP迁移到HTTPS是一项重要且必要的任务,因为这不仅关乎用户信息的安全,也有利于你的网站评级和粉丝的信心。在网络世界中,信息的安全就是一切,选择HTTPS,让您的网站更加安全,使您的用户满意,也使您感到满意。
181 18
|
7月前
|
网络协议
TCP/IP与OPC协议的深度比较
总的来说,TCP/IP和OPC协议各有其优点和应用场景。TCP/IP协议是网络通信的基础,而OPC协议则是工业自动化领域的重要工具。在实际应用中,我们需要根据具体的需求和场景,选择合适的协议。
251 11
|
7月前
|
安全 网络安全 定位技术
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
237 22
|
7月前
|
网络协议 数据安全/隐私保护 网络架构
|
8月前
|
网络协议 物联网
VB6网络通信软件上位机开发,TCP网络通信,读写数据并处理,完整源码下载
本文介绍使用VB6开发网络通信上位机客户端程序,涵盖Winsock控件的引入与使用,包括连接服务端、发送数据(如通过`Winsock1.SendData`方法)及接收数据(利用`Winsock1_DataArrival`事件)。代码实现TCP网络通信,可读写并处理16进制数据,适用于自动化和工业控制领域。提供完整源码下载,适合学习VB6网络程序开发。 下载链接:[完整源码](http://xzios.cn:86/WJGL/DownLoadDetial?Id=20)
299 12
|
8月前
|
缓存 网络协议 API
掌握网络通信协议和技术:开发者指南
本文探讨了常见的网络通信协议和技术,如HTTP、SSE、GraphQL、TCP、WebSocket和Socket.IO,分析了它们的功能、优劣势及适用场景。开发者需根据应用需求选择合适的协议,以构建高效、可扩展的应用程序。同时,测试与调试工具(如Apipost)能助力开发者在不同网络环境下优化性能,提升用户体验。掌握这些协议是现代软件开发者的必备技能,对项目成功至关重要。
|
9月前
|
人工智能 自然语言处理 决策智能
智能体竟能自行组建通信网络,还能自创协议提升通信效率
《一种适用于大型语言模型网络的可扩展通信协议》提出创新协议Agora,解决多智能体系统中的“通信三难困境”,即异构性、通用性和成本问题。Agora通过标准协议、结构化数据和自然语言三种通信格式,实现高效协作,支持复杂任务自动化。演示场景显示其在预订服务和天气预报等应用中的优越性能。论文地址:https://arxiv.org/pdf/2410.11905。
293 6

热门文章

最新文章