菜鸟笔记
提升您的技术认知

传输层TCP与UDP协议

传输层

传输层功能

  1. 定义应用层协议数据报文的端口号,流量控制
  2. 对原始数据进行分段处理

传输层所提供的服务

  1. 传输连接服务(主要是针对会话层的要求,对每一个传输连接去建立相应的连接)
  2. 数据传输服务(流量控制,差错控制,序列控制)

传输层的两个协议

  • TCP(Transmission Control Protocol)传输控制协议
  • UDP(User Datagram Protocol)用户数据报协议 

TCP协议与UDP协议

端口

含义:应用程序在计算机中的唯一标识

端口分类

  • 源端口:一般位于客户机
  • 目标端口:一般位于服务器

IP地址和端口的关系

注意:

  • 端口可分为虚拟端口和物理端口,其中虚拟端口指的是计算机内部或交换机路由器内的端口,不可见。
  • UDP/TCP首部中,端口占用2字节,因此可以计算出端口范围:0-65535
  • 防火墙可以设置开启和关闭某些端口来提高安全性

UDP协议 

前言:

  • UDP协议是面向无连接的,他减少了建立和释放连接的开销
  • UDP尽最大能力交付,不保证可靠传输
  • UDP不需要维护一些复杂的参数,首部只有8个字节
  • UDP协议不需要建立连接,直接发送数据,不会去重新排序,不需要确认

UDP报文格式

注意:

  • 16位UDP长度:指的是UDP首部的长度和UDP数据的总长度
  • 16位UDP检验和:将伪首部和首部和数据部分计算出一个值,用来检测UDP用户数据在传输过程中是否有错,有错就丢弃
  • 伪首部仅在计算检验和的时候起作用,并不会传递给网络层

检验和的伪首部

伪首部内容

  • 源IP地址
  • 目标IP地址
  • 保留位(固定为0)
  • 协议类型(封装所用的协议的数字表示形式)
  • UDP长度不包括伪首部长度,主要为UDP首部和数据部分的总长度

注意:

  • 伪首部固定12个字节
  • 伪首部仅在计算检验和的时候起作用,并不会传递给网络层

TCP协议

前言:该协议要求数据在传输前必须建立连接,数据在传输完成后必须释放连接。

TCP报文格式

TCP协议数据段的理解

  • 序号:占32位,传输过程中的每一个字节都有一个编号,在建立连接后,序号代表这一次传给对方多个数据包,每个数据包的起始位置所在字节的编号。
  • 确认号:占32位,标志位flags内的ACK为1时才有意义,代表期望对方下一次传过来的TCP数据部分的第一个字节编号(序号)
  • 数据偏移:占4位,数据偏移×4为首部的长度;由此可以算出TCP首部最长60字节;因为首部长度最小20字节,所以数据偏移最小为5
  • 保留:占6位,目前全为0
  • 标志位flags:占6位,主要用于分析控制数据段的状态
  • 窗口:占16位,主要用于TCP的流量控制,用以告知对方下一次允许发送数据的大小(真正的接收缓存区大小还需要乘窗口缩放系数)
  • 检验和:占16位,通过伪首部+首部+数据来计算出检验和;用来检测TCP数据段在传输过程中是否有错,有错就丢弃
  • 紧急指针:占16位,标志位flags内的URG为1时才有意义(若紧急指针为8,则代表TCP数据部分前8字节为紧急数据)

TCP的伪首部

前言:占用12个字节,仅在计算检验时起作用,并不会传输到网络层

伪首部内容

  • 源IP地址
  • 目标IP地址
  • 保留位(固定为0)
  • 协议类型(封装所用的协议的数字表示形式)
  • TCP长度不包括伪首部长度,主要为TCP首部和数据部分的总长度

注意:

  • TCP首部中仅仅有4个字段(数据偏移)记录了TCP报文的首部长度,并没有字段记录了TCP报文的数据长度,但是伪首部中有TCP首部和数据的总长度(TCP长度)
  • TCP/UDP的数据长度完全可以由IP数据包的首部推测出来:传输层的数据总长度=网络层的总长度-网络层的首部长度-传输层的首部长度

标志位flags

  • UGR:紧急指针
  • ACK:确认响应序号有效(确认建立连接)
  • PSH:数据传输标记
  • RST:重置连接(当RST=1时表明连接出现问题,必须释放连接后重新建立连接)
  • SYN:SYN=1,ACK=0代表这是一个建立连接的请求
  • FIN:发送端完成发送任务,要求释放连接

注意:flags的设置通过设置0/1来实现

理解TCP的序号与确认号

TCP的几个要点

  • 可靠传输
  • 流量控制
  • 拥塞控制
  • 连接管理

TCP可靠传输

可靠传输:客户端发起请求给服务器,服务器收到请求给客户端返回数据,若服务器返回的数据比较大那么服务器不可能一次性把数据传出去,此时数据就会被分成好几个段来进行发送,若发送的过程中某个数据包丢失(客户端没有确认收到)那么服务器只会将该包重新发送

停止等待-ARQ(automatic repeat-request)自动重传请求

例子:A发送3个包给B(M1、M2、M3)

  • 正常情况:A发送M1到B,B收到后发确认请求到A,A收到确认后发送M2到B,以此类推
  • 超时情况:A发送M1到B(M1在运输过程出现差错)B丢弃有差错的报文,不向A响应确认,超时后A重新发送M1给B,B收到完好的M1后向A响应确认
  • 确认丢失:A发起M1向B,B收到后向A响应确认M1(传输过程确认失效),A超时仍没有收到确认,再向B重新发送M1,B收到后丢弃重复的M1,重新向A响应确认,A收到确认响应
  • 确认迟到:A发送M1给B,B收到后响应确认到A,因为响应超时A向B重传M1,B收到后丢弃重复的M1后响应确认到A,此时A收到确认可以继续发送其他数据包,过一会B的确认到达,A不会做任何动作

连续ARQ协议+滑动窗口协议

注意:

  • 滑动窗口的大小由接收方(B)决定
  • 有些系统重传5次还未成功就会发送RST报文断开TCP连接
  • 接受方在拿到发送方发送方的数据的时候首先会放到缓存(有大小限制)内,若缓存将要不够用那么就会告诉发送方特定的接收窗口大小(接收窗口大小不是固定死的)

具体案例

电脑A向电脑B发送的数据

发送的过程:

SACK选择性确认

前言:在TCP通信过程中,若发送序列中间某个数据包丢失(比如1、2、3、4、5中的3在发送过程中丢失了)不用SACK技术的话TCP会通过重传最后确认的分组后续的分组(最后确认的2,会重传3、4、5)这样原先已经正确发送的分组也可能重复发送(比如4、5)降低了TCP的性能;为了改善上述情况,发展了SACK技术,它可以告诉发送方那些数据丢失,那些数据已经提前收到,这样TCP只重新发送丢失的包(3)不用发送后续的包(4、5)

举例: 

理解:假设发送方发了201-1000这么多数据,接收方仅仅接受了棕色范围内的数据,白色范围内的数据都没接收;那么就会告诉发送端,自己接受了(左边界301右边界401、左边界501右边界601、左边界701右边界801、左边界901右边界1001)的数据。

注意:

  • SACK信息会放在TCP首部的选项部分
  • kind:占1字节;值为5就代表这是SACK选项(就意味着TCP选项有很多种)
  • length:占1字节;表明SACK选项共占多少字节
  • left edge:占4字节,左边界
  • right edge:占4字节,右边界
  • 因为选项部分最多40个字节,40字节仅有2字节是刚需,留给左右边界的仅有38字节,因为左右边界一组为8字节,那么仅能存放4组左右边界(TCP数据偏移计算得知TCP首部最长60字节,有20字节的固定长度,所以选项部分最长40字节)

传输层数据分段

为什么选择在传输层就进行数据分段,而不是等到网络层再分片传递给数据链路层?

因为可靠传输是在传输层进行控制的,若在传输层不分段,那么一旦出现数据丢失,那么整个传输层的数据都得重传;若在传输层分了段,那么一旦出现数据丢失,只需要重传丢失的那些段即可。

流量控制

前言:接受方在拿到发送方发送方的数据的时候首先会放到缓存,若接收方的缓存满了发送方还在疯狂的发送数据,那么接收方只能把收到的数据包丢掉,大量的丢包会极大的浪费网络资源,所以要进行流量控制

含义:让发送方发送的速率不要太快,让接收方来得及接收处理

原理:

  • 通过确认报文中的窗口字段来控制发送方的发送速率
  • 发送方发送的窗口大小不能超过接收方给出的窗口大小
  • 当发送方收到接收窗口大小为0时,发送方就会停止发送数据

具体案例

流量控制的特殊情况

起初接收方给发送方发送了0窗口的报文段,后面接收方又有了一些储存空间,给发送方发送了非0窗口的报文段丢失了发送方的发送窗口一直为0,双方陷入僵局

解决办法:当发送方收到0窗口通知时,发送方停止发送报文,并且同时开启一个定时器,隔一段时间就发送个测试报文去询问接收方最新的窗口大小,若接收窗口大小还是0,则发送方再次刷新启动定时器

拥塞控制

前言

理解:

  • 防止过多的数据注入到网络
  • 避免网络中的路由器或链路过载

注意:拥塞控制是一个全局性的过程涉及到所有主机、路由器以及降低网络传输性能有关的所有因素,是大家共同努力的结果,相比而言,流量控制是点对点的通信控制

拥塞控制方法

  • 慢开始(slow start)
  • 拥塞避免(congestion avoidance)
  • 快速重传(fast retransmit)
  • 快速恢复(fast recovery)

基本知识

  • MSS:(MAXimum Segment Size)每个段最大数据部分大小,建立连接时确定,发送方的每个段都不能超过该值
  • cwnd:(congestion window)拥塞窗口(使整个网络恰好拥塞的最小窗口)
  • rwnd:(receive window)接收窗口(接收方告诉发送方最多发送的数据是多少)
  • swnd:(send window)发送窗口(实际发送数据的窗口)

拥塞窗口、接收窗口、发送窗口的理解

假设接收方窗口大小为3000,那么发送方的发送窗口发送的数据最多为3000,而拥塞窗口是会经常变动的,假设网络现在繁忙不能发送太多拥塞窗口只有2000(没有超过接收窗口的3000),那么发送窗口和拥塞窗口都是相等的;若现在网络很顺畅,拥塞窗口有5000,而对方接收窗口为3000,那么接收窗口等于发送窗口。

总结:发送窗口=min(接收窗口,拥塞窗口)

拥塞控制-慢开始

理解:接收方告诉发送方,让发送方最多发送3000数据,每个包的数据部分不能超过100;接收方收到请求首先先发1个包,然后收到对方的确认了,然后发送方明白了(发送一个包没问题网络不堵,可以再给加点量),然后发送方发了2个包,对方又都确认了,那再发4个,对方都确认,那么再发8个。

拥塞窗口随时间变化关系图

总结:cwnd(拥塞窗口)的初始值比较小,然后随着数据包被接收方确认(收到一个ACK)cwnd就会成倍增长(指数级增加)

拥塞避免

注意:

  • ssthresh(slow start threshold):慢开始阈值,cwnd达到阈值后,以线性方式增加
  • 拥塞避免(加法增大):拥塞窗口缓慢增大,以防止网络过早出现拥塞
  • 判断网络拥塞:发送方发送的数据没有收到对方的确认,那么就考虑重传(有些包丢了)就可以说明网络可能出现拥塞
  • 乘法减小:当发送方感知到网络可能拥塞了就把ssthresh减为峰值的一半,与此同时执行慢开始算法(cwnd又恢复到初始值)

拥塞控制-快重传

理解:

  • 接收方:每当收到一个失序的分组后就立即发出重复确认使发送方及时知道有分组没有到达,而不是等待自己发送数据时才进行确认
  • 发送方:只要连续收到三个重复确认(总共4个相同的确认)就应当立即重传对方尚未收到的报文段,而不必继续等待重传计时器到期后再重传

快恢复

理解:当发送方连续收到三个重复确认,就执行“乘法减小”算法,把ssthresh为减为峰值的一半,与慢开始不同的是现在不执行慢开始算法,即cwnd现在不会恢复到初始值,而是把cwnd值设为ssthresh减半后的数值然后开始执行拥塞避免算法(加法增大),使拥塞窗口缓慢线性的增大

TCP连接管理

注意:连接管理中建立连接的三次握手以及四次挥手的报文中只有TCP报文头部,而没有TCP报文数据部分

TCP建立连接三次握手

理解:

  1. 客户机向服务器发送请求建立连接,控制位syn=1,ACK没有等于1说明这是一个请求建立连接,这时会自动生成一个序号seq(这个序号是随机的) 这个序号我们用x来表示,向服务器发起请求
  2. 服务器收到请求后,他会向客户机发送确认请求,进而SYN=1,ACK=1,同时有了确认的序列号ack=x+1(期望发送原来序列号的下一个请求)这时服务端随机生成一个序列号seq=y;
  3. 客户机收到服务器发来的确认,客户机进行确认ACK=1,客户机不会再发请求了,因此没有SYN,同时有了确认序号ack=y+1(期望服务器执行下一步操作),seq=x+1
  4. 开始进行数据传输

TCP建立连接三次握手的原因

若建立连接只需要两次握手,那么可能出现:客户端发送的第一个请求因为网络延时,在连接释放以后的某个时间才到达服务端,服务端收到该请求后响应了这个迟到的连接请求,但是刚刚客户端已经接受了数据,进而不会发起http请求,这样服务器就会一直等待进而浪费了资源(一直处于建立连接状态)

注意:若第三次握手失败了,此时server的状态为syn-rcvd,若等不到客户端的ACK,server会重新发送SYN+ACK包,若此时server多次重发SYN+ACK都等不到客户端的ACK,就会发送RST包,强制关闭连接

连接过程(以http的get请求为例——数据部分为4字节)

注意:这里使用的seq和ack都是相对的

1.首先客户端开始发起http的get请求,seq为1(相对于之前建立连接的x)ack为1(相对于之前建立连接的y)含义为期望服务端开始发送数据;

2.然后服务器收到请求连续发送4个包(之前的连续arq协议)

这里面的seq就是发送的每个数据包的起始字节序号,这里的ack就是希望客户端开始发送第k+1个字节;

3.客户端收到对方的4个TCP数据段,TCP数据部分占0字节,seq标识这是发给服务端的k+1个字节,ack标识期望服务端发送b1+b2+b3+b4+1个字节

TCP释放连接四次挥手

前言:

  • TCP是全双工通信
  • TCP/IP协议栈上,允许任何一方发起断开连接请求

理解:

  1. 数据传输完成后,客户机向服务器发送释放连接请求FIN=1,同时随机生成序列号u
  2. 服务端收到客户端的请求进行确认ACK=1,随机生成序列号seq=v
  3. 此时服务器这边若也觉得没有东西可以发给客户端,服务器也会发释放连接请求给客户端(FIN=1)随机生成序列号w
  4. 客户端收到服务端的请求对其进行确认ACK=1(告诉服务器知道没有东西发给自己了)进而双方关闭连接

为什么释放连接需要四次挥手

  • 第一次挥手:当客户端发出FIN报文时表示客户端告诉服务器,自己已经没有数据要发送了,但是还是可以接收到服务器的数据
  • 第二次挥手:当服务器返回ACK报文时,表示服务器已经知道客户端没有数据要发送了,但是服务器还是可以发送数据到客户端
  • 第三次挥手:当服务器也发送FIN报文时表示服务器告诉客户端,服务器也没有数据要发送了
  • 第四次挥手:当客户端返回ACK报文时,表示客户端已经知道服务器没有数据要发送了,随后正式断开整个TCP连接

客户端发送ACK报文后需要时间等待原因

若客户端发送ACK后马上释放了,然后又因为网络原因,server没有收到client的ACK,server就会重发FIN可能出现以下情况

  • client没有任何响应,服务器那边会干等,甚至多次重发FIN,浪费资源
  • client刚好有个新应用程序,分配了同一个端口号,新应用程序收到FIN后马上开始执行断开连接操作,但是本来他想和服务器建立连接的

时间等待的确认

一般是2倍的MSL(MAXimum Segment Lifetime,最大分段生存周期)MSL是TCP报文在internet上的最大生存时间,每个具体的TCP实现都必须选择一个确定的MSL值,RFC 1122建议是2分钟,这样可以防止本次链接中产生的数据包误传到下一次连接中(因为本次连接中的数据包都会在2MSL时间内消失)