【计算机网络】TCP协议详解

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: TCP是面向字节流的,可以多次的接收和发送,对于应用层来说,一连串的字节数据,不知道从哪到哪算一个完整的应用层数据包,对应发送多少次算一个应用层完整格式的数据,和接收多少次算一个应用层完整格式的数据就不知道了

1. TCP协议头部格式

image.png


源/目的端口:表示数据从哪个进程发送,发送到哪个进程去

32位序号:发送的数据按照一个字节一个编号存放进去

32位确认号:用于给对方的响应,值为收到TCP报文段的序号值加1

4位TCP报头长度:表示TCP头部有4个字节(32位),所以TCP头部最大长度为15*4=60

6个boolean值标志位:

URG:紧急指针是否有效

ACK:确认号是否有效

PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走

RST:对方要求重新建立连接,把携带RST标识的称为复位报文段

SYN:请求建立连接,把携带SYN标识的称为同步报文段

FIN:通知对方,要关闭连接了,把携带FIN标识的称为结束报文


16位窗口大小:进行流量窗口控制

16位校验和:检验数据是否一致

16位紧急指针:标识哪部分数据是紧急数据

2. TCP协议原理

TCP协议是对数据传输提供的一个管控机制,主要体现在可靠和效率两个方面,即在保证数据可靠传输的情况下尽可能的提高效率


2.1 可靠传输机制

2.1.1 确认应答机制

向对方发送一个数据报,对方要返回一个确认应答的数据报


实现的方式:

image.png



说明:


发送的数据是基于TCP报头中的“32位序号”来保存的,一个字节对应一个序号

确认应答的数据是基于TCP报头中的“32位确认序号”来保存的,ack(确认信息)标志位置为1,返回某个序列号,说明某个序列号之前的数据全部接收到

有了确认应答,它才可以继续发送后边的数据

2.1.2 超时重传机制

发送的数据报可能因为网络拥堵等原因,超过一定时间,还没有收到确认应答的数据报,就需要重新发送


没有收到确认应答,可能是因为发送数据时候就已经发生了丢包

 image.png


也可能是因为ACK丢包了

微信图片_20221030151657.png

这种情况,主机B可能会接收到许多重复的数据,基于TCP协议报头中的“32位序号”可以识别到哪些包是重复的包,并把重复的包丢掉,达到去重的效果


超时时间如何确定?


如果超时时间设置的太长,会导致重传的效率

如果超时时间设置的太短,会导致频繁发送重复的数据


因此TCP协议为了保证在任何环境中都能有较高性能的通信,系统会动态的计算这个超时时间


超时以500ms为一个单位,每次判定超时重发的时间都是500ms的整数倍

重发一次,仍然不能收到应答,等待2*500ms后再进行重传

仍然等不到应答,等待4*500ms进行重传,以此类推,以指数形式增长

累积到一定重传次数,TCP协议认为网络或者对端主机出现异常,强制关闭连接

2.1.3 连接管理机制(三次握手,四次挥手)

真正发送数据之前,要先通过三次握手建立连接,不需要发送数据了,通过四次挥手断开连接


三次握手

image.png

 


客户端向服务端发送SYN,申请建立客户端到服务端的连接

服务端返回ACK(第一次SYN的应答)和SYN,申请建立服务端到客户端的连接

客户端收到数据,状态置为ESTABLISHED,表示客户端到服务端连接建立完成,并且发送ACK(第二次SYN的应答),服务端收到数据,状态置为ESTABLISHED,表示服务端到客户端的连接建立完成

四次挥手

image.png


说明:关闭的时候服务端申请关闭或者客户端申请关闭都可以


客户端发送FIN到服务端,申请关闭客户端到服务端的连接

服务端收到FIN状态置为CLOSE_WAIT,并返回ACK应答(这个动作是系统实现TCP协议栈默认执行的,不需要程序来调用代码)

服务端发送FIN到客户端,申请关闭服务端到客户端的连接(程序手动调用socket.close发送)

客户端收到FIN返回ACK应答,并进入TIME_WAIT时间等待状态,客户端等待一段时间后,状态置为CLOSED,服务端收到应答后,状态置为CLOSED

思考:


为什么服务端不将ACK和FIN合并一起发送,形成三次挥手呢?

答:因为服务端状态置为CLOSED_WAIT说明服务端准备关闭连接,但是服务端可能还在继续发送数据,得处理完之前的数据,还可以执行一些关闭连接前的工作,如消耗资源等 ,所以是先给客户端发送应答,再处理完数据再向客户端发送FIN申请关闭连接


为什么客户端要等待一段时间状态才置为CLOSED,而不之间将状态置为CLOSED?

答:如果客户端给服务端的ACK丢包后,服务端得重新给和客户端发送FIN,此时客户端得给服务端应答,所以此时状态不能置为CLOSED,得等待一段时间确保服务端收到客户端的应答


2.1.4 流量控制

接收端主机处理数据的速度有限,如果发送端发送数据太快,导致接收端缓冲区被填满,这时,发送端继续发送数据的话就会造成丢包,继而引起丢包重传等一些列连锁反应,因此TCP协议根据接收端接收数据的能力,来决定发送端发送数据的速度,这个机制就叫作流量控制


接收端将自己剩余缓冲区大小存入TCP头部中的“16位窗口大小”字段 ,通过ACK通知发送端

窗口大小越大,说明网络吞吐量越高

发送端根据接收到这个窗口的大小,控制自己的发送速度

如果接收缓冲区满了,就会将窗口设置为0,这时,发送端不在发送数据,而是定期的发送一个窗口探测数据段,让接收端将窗口大小告诉发送端

2.1.5 拥塞控制

刚开始,发送端网络状况不明,如果贸然发送大量数据,就会造成大量丢包,所以TCP协议引入慢启动的方式,先发少量数据探探路,再决定按照多大速度发送数据


此处引入拥塞窗口,刚开始时,拥塞窗口设置为1,每收到一个ACK时,拥塞窗口加1,每次发送数据的时候,拥塞窗口和流量窗口的较小的值作为实际发送的窗口,即滑动窗口的大小


注意:上述增长方式是指数级别的,“慢启动”只是开始时慢,但是增长速度非常迅速


拥塞窗口变化的方式


为了不增长那摩快,引入一个慢启动的阈值,当拥塞窗口的大小超过了这个阈值,不在按照指数方式增长,而是按照线性方式增长,如下图所示:

image.png


开始时,慢启动的阈值为窗口的最大值

网络拥塞时,拥塞窗口置1,慢启动阈值变为拥塞窗口/2,重新开始增长


2.2 效率机制

2.2.1 滑动窗口

前面的确认应答机制指出,对每一个发送的数据都对应有一个ACK确认应答,这样采取一发一收的方式有一个很大的缺点就是效率太差,为了提高效率采用滑动窗口,即一次性发送多个数据

image.png


窗口大小:指无需等待而可以继续发送数据的最大值,上图的窗口大小为4000个字节(四个段)

具体如何设置窗口大小:min(流量窗口的大小,拥塞窗口的大小)

窗口如何滑动:接收到的ACK下一个是n,滑动到n-1的位置

操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答,只有应答过的数据才能从缓冲区中删掉


如果出现了丢包,如何确保可靠传输?


情况一:数据已经收到,返回的ACK应答丢包

image.png


这种情况下,部分ACK丢了不要紧,因为可以通过后续的ACK进行确认


情况二:发送数据的时候就已经丢包

微信图片_20221030151855.png


说明:


当1001~2000这段报文丢失后,发送端一直会收到1001这样的ACK

如果发送端主机连续三次收到相同的ACK如1001应答,那发送端主机就会重新发送1001~2000数据

此时,接收端收到1001~2000数据后,再次返回的ACK应答就是7001了,因为2001~7000数据都已经接收到了,被放到接收端操作系统内核的接收缓冲区了

这种机制,即时不超时也会发生重传,称作“高速重发控制”也叫“快重传机制”


2.2.2 延迟应答

如果接收端主机接收到数据时,立刻返回ACK应答,这时候返回的流量窗口就比较小,但是流量窗口越大,网络吞吐量越大,传输效率就越高,所以等待一部分时间,待接收端处理完一部分数据 ,就可以将流量窗口设置为大一点的值,这样网咯吞吐量大,效率高


延迟是为了高吞吐量,但是也不能无限延迟


数量限制,每隔n个包就应答一次

时间限制,超过最大延迟时间,就应答一次

具体的数量和时间,不同操作系统有差异,一般n取2,超时时间取200ms


2.2.3 捎带应答

服务端接收到客户端的消息后,要返回一个ACK有时候可能需要返回一个响应,此时ACK可以搭载顺风车,和响应合并为一个数据返回,不用再将ACK和响应数据分开发送


3. 粘包问题

TCP是面向字节流的,可以多次的接收和发送,对于应用层来说,一连串的字节数据,不知道从哪到哪算一个完整的应用层数据包,对应发送多少次算一个应用层完整格式的数据,和接收多少次算一个应用层完整格式的数据就不知道了


如何解决粘包问题?明确包的边界


对于定长的包,每次都按照固定大小读取即可

对于变长的包,可以在包与包之间明确分隔符(应用协议,程序员自己定,只要保证分隔符和正文不起冲突即可)


4. TCP的异常情况

进程终止:进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别

机器重启:和进程终止的情况相同

机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了就会进行reset,即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在,如果对方不在,也会把连接释放

另外,应用层的某些协议,也有一些这样的检测机制,例如HTTP长连接中,也会定期检测对方的状态,例如QQ,在QQ断线之后,也会定期尝试重新连接


5. TCP协议特点总结

有连接:通过三次握手建立连接后才可接发数据,TCP协议是全双工的,即每端既可以发也可以收

可靠传输:网络数据传输是一跳一跳的,经过路途中的设备可能发生数据丢失,可靠传输是可能发生数据丢失但有机制保证对方能接收到

面向字节流:可以多次的收发数据(连接没有关闭时,可以多次的接收和发送数据)

有接收缓冲区和发送缓冲区:发送数据时,是先写到发送缓冲区,再刷新缓冲区(flush)

大小不受限制:多次的收发数据,每次的数据可以很大


6. 基于TCP的应用层协议

HTTP

HTTPS

SSH

Telnet

FTP

SMTP

也包括自己写TCP程序时自定义的应用层协议  


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
8天前
|
网络协议 C语言
C语言 网络编程(十三)并发的TCP服务端-以进程完成功能
这段代码实现了一个基于TCP协议的多进程并发服务端和客户端程序。服务端通过创建子进程来处理多个客户端连接,解决了粘包问题,并支持不定长数据传输。客户端则循环发送数据并接收服务端回传的信息,同样处理了粘包问题。程序通过自定义的数据长度前缀确保了数据的完整性和准确性。
|
8天前
|
网络协议 C语言
C语言 网络编程(十一)TCP通信创建流程---服务端
在服务器流程中,新增了绑定IP地址与端口号、建立监听队列及接受连接并创建新文件描述符等步骤。`bind`函数用于绑定IP地址与端口,`listen`函数建立监听队列并设置监听状态,`accept`函数则接受连接请求并创建新的文件描述符用于数据传输。套接字状态包括关闭(CLOSED)、同步发送(SYN-SENT)、同步接收(SYN-RECEIVE)和已建立连接(ESTABLISHED)。示例代码展示了TCP服务端程序如何初始化socket、绑定地址、监听连接请求以及接收和发送数据。
|
8天前
|
网络协议 C语言
C语言 网络编程(十四)并发的TCP服务端-以线程完成功能
这段代码实现了一个基于TCP协议的多线程服务器和客户端程序,服务器端通过为每个客户端创建独立的线程来处理并发请求,解决了粘包问题并支持不定长数据传输。服务器监听在IP地址`172.17.140.183`的`8080`端口上,接收客户端发来的数据,并将接收到的消息添加“-回传”后返回给客户端。客户端则可以循环输入并发送数据,同时接收服务器回传的信息。当输入“exit”时,客户端会结束与服务器的通信并关闭连接。
|
8天前
|
网络协议 C语言
C语言 网络编程(十二)TCP通信创建-粘包
TCP通信中的“粘包”现象指的是由于协议特性,发送方的数据包被拆分并在接收方按序组装,导致多个数据包粘连或单个数据包分割。为避免粘包,可采用定长数据包或先传送数据长度再传送数据的方式。示例代码展示了通过在发送前添加数据长度信息,并在接收时先读取长度后读取数据的具体实现方法。此方案适用于长度不固定的数据传输场景。
|
8天前
|
缓存 网络协议 网络性能优化
C语言 网络编程(二)TCP 协议
TCP(传输控制协议)是一种面向连接、可靠的传输层协议,通过校验和、序列号、确认应答等机制确保数据完整性和可靠性。通信双方需先建立连接,再进行通信,采用三次握手建立连接,四次挥手断开连接。TCP支持任意字节长度的数据传输,具备超时重传、流量控制及拥塞控制机制。三次握手用于同步序列号和确认双方通信能力,四次挥手则确保双方均能完成连接关闭操作,保证数据传输的可靠性。
|
8天前
|
网络协议 C语言
C语言 网络编程(十)TCP通信创建流程---客户端
在TCP通信中,客户端需通过一系列步骤与服务器建立连接并进行数据传输。首先使用 `socket()` 函数创建一个流式套接字,然后通过 `connect()` 函数连接服务器。连接成功后,可以使用 `send()` 和 `recv()` 函数进行数据发送和接收。最后展示了一个完整的客户端示例代码,实现了与服务器的通信过程。
|
8天前
|
网络协议 视频直播 C语言
C语言 网络编程(三)UDP 协议
UDP(用户数据报协议)是一种无需建立连接的通信协议,适用于高效率的数据传输,但不保证数据的可靠性。其特点是无连接、尽力交付且面向报文,具备较高的实时性。UDP广泛应用于视频会议、实时多媒体通信、直播及DNS查询等场景,并被许多即时通讯软件和服务(如MSN/QQ/Skype、流媒体、VoIP等)采用进行实时数据传输。UDP报文由首部和数据部分组成,首部包含源端口、目的端口、长度和校验和字段。相比TCP,UDP具有更高的传输效率和更低的资源消耗。
|
11天前
|
监控 安全 网络安全
深入理解SNMP:网络管理的关键协议
【8月更文挑战第31天】
37 1
|
5天前
|
网络协议
网络协议概览:HTTP、UDP、TCP与IP
理解这些基本的网络协议对于任何网络专业人员都是至关重要的,它们不仅是网络通信的基础,也是构建更复杂网络服务和应用的基石。网络技术的不断发展可能会带来新的协议和标准,但这些基本协议的核心概念和原理将继续是理解和创新网络技术的关键。
14 0
|
11天前
|
存储 运维 监控