什么是TCP协议
TCP协议,即Transmission Control Protocol,传输控制协议,是一种传输层通信协议
TCP协议数据报文格式
报文由报头和数据组成,这里详解下报头的格式
源端口号和目标端口号:用来标识数据从哪个程序发出,由哪个程序接收
序号:TCP通信过程中,发送方将数据分为多个数据段,并为每个数据段分配一个唯一的序号
确认序号:表示接收方成功接收到数据后,期望收到的下一个数据段的序号,与ACK相关联
头部长度:表示报头的长度,头部长度的字段值*4,可以得到以字节为单位的TCP头部长度
保留:用于保留未来可能扩展的功能
标志位: URG:紧急指针是否有效
ACK:确认号是否有效
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:要求重新建立连接,携带RST标识被称为复位报文段
SYN:请求建立连接,携带SYN标识被称为同步报文段
FIN:通知对方,本段要关闭了,携带FIN标识被成为结束报文段
窗口大小:无需确认应答,可以发送数据的最大值
检验和:用来检验数据是否完整地成功送达
紧急指针:如果该报文含有紧急指针,则需要优先处理该段紧急数据,紧急指针的值与序号的相加值为紧急数据的最后一个字节位置
选项:用于向TCP报文中添加额外的功能和参数,由头部长度控制字段长度
TCP协议中的重要机制
1.确认应答(可靠机制)
确认应答的机制与报文中的序号和确认序号有关,如上图,主机A第一次将1到1000字节的数据传输给主机B,这段数据序号为1,若主机B成功接收到这段数据,那么它就会向主机A返回一个ACK为1的报文段,并且将确认序号设置为1001,表示1到1000字节的数据已经收到,接下来准备接收序号1001的数据段,然后主机A又将1001到2000的数据传输给主机B,接下来的过程同上
确认应答是TCP实现可靠传输最重要的机制
2.超时重传(可靠机制)
如果主机A在一个特定的时间间隔中没有收到主机B的确认应答报文,那么就会触发超时重传,再传输一次数据给主机B
关于等待的时间,初始等待时间与系统相关,也可以通过配置内核参数来修改,每经过一次超时重传,等待时间会被拉长,当时间拉长到一定程度时,仍然无法收到确认应答的报文,便放弃重传
没有收到主机B的应答报文,分为两种情况,一、数据没有传输到主机B,二、数据传输到了主机B,但是主机A的没有收到主机B的应答报文
若是第一种情况,我们假设丢包率是0.1%,那么重传后丢包的概率就是0.0001%,经过超时重传,丢包率大大的下降,数据传输的成功性大幅度提升,如果经过两次甚至多次重传都没办法解决问题,说明当前网络环境已经出现了较大故障
若是第二种情况,主机B已经收到了主机A的数据,但主机A并不知道,就会一直触发超时重传,这会导致主机B重复接收冗余的数据,不过TCP已经帮我们解决这个问题了,TCP内有一个接收缓冲区,会保存当前接收到的数据,已经数据的序号,如果发送过来的数据已经存在于接收缓冲区中,那么就会将新发送过来的数据抛弃,确保接收方只接收到一次数据,只要主机A等待一段时间结束超时重传即可
3.连接管理(可靠机制)
建立连接:三次握手
第一次:主机A向主机B发送SYN
第二次:主机B向主机A发送ACK和SYN(ACK和SYN可以合并在一个报文里)
第三次:主机A向主机B发送ACK
同步报文段用来表示想要建立连接,应答报文用来表示收到消息
三次握手的意义:一、确认当前网络环境是否正常。二、双方的发送和接受功能是否正常。三、双方对数据传输的一些参数进行协商(如数据段的序号)
接下来我用一个例子来解释下为什么需要三次握手,在与朋友开黑的过程中,我们都需要调试自己的耳机和麦克风,比如有A,B两个人进行调试工作
A说喂,B听到了A的喂,B知道自己的耳机与A的麦克风是好的
于是B回复收到,A听到了B的收到,就知道自己的耳机,麦克风与B的耳机与麦克风是好的
于是A向B回复一切正常,于是A和B都知道了双方的耳机与麦克风都是好的
这就是为什么需要三次握手,少一次无法达到效果,多一次则多余
断开连接:四次挥手
第一次:主机A向主机B发送FIN
第二次:主机B向主机A发送ACK
第三次:主机B向主机A发送FIN
第四次:主机A向主机B发送ACK
主机B发送ACK和FIN不能合并成一个报文,因为主机B接收到主机A发送的FIN,会立即返回ACK,这是内核响应的,而返回FIN需要经历一系列的代码
4.滑动窗口(效率机制)
窗口大小表示无需等待ACK发送数据的最大值
上面的滑动窗口一次性可以发送四个数据段,当收到一个ACK时,窗口就向右边移动一个数据段,表示发送一个数据段,窗口左边的数据就是已经发送的数据,中间是正在发送,而右边就是待发送的数据
在滑动窗口下,丢包了如何进行重传?
一、ACK丢失
部分的ACK丢失并不影响,只要收到后续的ACK就代表前面的数据已经收到
二、数据包丢失,如果其中一段数据丢失,那么接收端就会一直发送与该数据相关的确认应答,假设序号1001的数据段丢失,那么接受端就会一直发送确认应答为1001的ACK,这样发送端看到如此多确认应答为1001的ACK就知道这段数据丢失了,就会触发重传
当双方传输的数据量大且频繁时,就会进入滑动窗口模式
5.流量控制(可靠机制)
接收端处理数据的能力有限,如果接受缓冲区满了,而发送端还在发送数据的话,那么就会造成丢包,因此接收方可以通过自己的接受能力来控制发送方的发送速度,这个机制就是流量控制
接收端通过ACK,将自己的缓冲区大小放入TCP的窗口大小字段,发送给发送端,发送端就会根据这个ACK来调整自己的发送速度,若接收端缓冲区满了,就会将窗口设置为0,发送端此时不再发送数据,但是需要定时发送一个窗口探测数据段,触发接收端ACK,以此来知道,接收端此时的接受能力
6.拥塞控制(可靠机制)
TCP引入慢启动机制,先发少量数据,再慢慢增加数据,摸清当前网络拥堵状况,再决定以怎样的速度进行传输
发送开始时,先设置一个小的拥塞窗口,每返回一个ACK增加拥塞窗口的大小,每次发送数据包时,取拥塞窗口,与ACK返回的窗口大小的较小值,作为实际采用的窗口
7.延迟应答(效率机制)
如果主机一收到数据便放回应答,那么返回的窗口可能比较小,如果稍微延迟一点,那么接收端就可以多处理点数据,就可以放回更大的窗口,提升传输的效率
8.捎带应答(效率机制)
在延迟应答的基础上,ACK会稍微晚一些返回,这段时间内如果接收端正好有一些数据要发给发送端,那么就可以捎带ACK一起返回
TCP粘包问题
TCP面向字节流,应用程序看到一连串的字节数据不知道哪一部分是一个完整的数据包,对于这个问题,可以这么解决
对于定长的包,按固定的大小读取
对于变长的包,可以在包头位置明确包的长度,或者在包与包之间明确分隔符
TCP异常情况
1、进程崩溃
触发FIN,对方收到后,返回ACK与FIN,这边在进行ACK,是正常流程(线程崩溃不影响TCP的连接)
2.主机关机
若在系统关闭前,对端的ACK与FIN已经传到,此时系统仍然可以返回ACK,于是同第一种情况一样,若系统已经关闭了,对方没有收到ACK,那么就会进行重传,重传多次没响应,就会放弃链接
3.主机掉电
A.若接收方掉电,发送方会一直等待ACK,触发超时重传,发起复位报文段,如果仍然没有效果,便断开连接
B.若发送方掉电,接收方长时间没收到消息,就会给发送方发起一个“心跳包”,这个包不带任何业务数据,仅仅希望想触发对方的应答,如果仍没有效,则断开连接
4.网线断开
同主机掉电的情况
谢谢大家,如果觉得我的文章对你有帮助,请点个赞吧!