传输层
只有主机才会有传输层
主机(五层) - 传输设备(三层) - 主机(五层)
传输层功能:进程与进程之间的通信
网络层功能:主机与主机之间的通信
复用:不同进程可以共用一个传输层传输到网络层
分用:剥去报文之后(从网络层收到数据后),能够送交给正确的进程
QQ给女朋友发的消息,微信上是收不到的
网络层首部校验和 :只检查了头部
传输层 对数据部分进行校验(差错j检测)
导学
TCP和UDP比较
TCP:
传数据之前需要建立连接,传送结束后释放连接
不提供广播和多播
UDP:
只管发不管你收不收得到
传输层的寻址 - 端口号
端口号分类
常见端口号
套接字socket = (主机IP地址,端口号)
UDP
在IP数据报基础上,增加了复用分用和差错检测
UDP面向报文:不切分,给多少就是多少,完整的
所以要选择合适的报文.尽量不要后续在网络层分片
无拥塞控制:不会从源头上限制发送报文的速度
拥塞会适量的丢包,但影响不大
UDP首部格式
UDP检验和
当校验的时候,会给数据添上伪首部
发送端校验
接收端校验
TCP
可以实现全双工通信
发送缓存: 存储了未发送的数据 和 已经发送但是还未确认达到的数据
接收缓存:存储了到达了未被读取的数据 和 没有按序到达的数据
流: 字节序列 ,流入进程或流出进程
TCP 报文段首部格式 ⭐
填充字段的作用: 用来凑数的 ,保证首部是4字节整数倍
序号字段:该报文中的第一个字节
1 |1 2 3 , 4 | 4 5 6
确认号:期待对方发送的第一个字节
已发送123 接下来发送456, 4就是确认号
数据偏移:数据起始处,距离TCP报文的起始处的 距离
数据偏移:正好是首部长度
首部长度 = 固定长度20字节 + 选项 +填充
窗口
对于接收端而言,所能容纳的最大的数据量
A给B发文件,B得告诉A,自己的窗口是多少,A就知道如何设置发送缓存了
例: 若确认号701 ,窗口为1000 ,所以从701开始发送数据 ,接收缓存空间就是 701~1700
检验和
传输层 检验首位 + 数据部分
紧急指针
指明了紧急数据的末尾 在 报文段中的位置
紧急指针为70 则0~70就是紧急数据
选项(长度可变的字段)
最大报文段长度MSS等
控制位
URG 紧急位
对于发送方而言
URG = 1 ,有高优先级的数据来了, 结合紧急指针使用
不在缓存中排队了,赶紧发送出去
ACK 确认位
ACK = 0 ,确认号无意义
所以建立连接成功后ACK为1
通俗理解; ACK= 1 对方存在
PUSH 推送位
对接收端而言 , 尽快交付PUSH=1的应用进程 , 不用等缓存填满了再向上交付
RST 复位
TCP出现严重差错,释放当前连接并且重新建立连接
SYN 同步位
SYN=1 ,表示 这是一个请求建立连接的报文
FIN 终止位
FIN = 1.报文段发送方数据发送完毕, 释放连接
TCP连接管理
三个过程:
连接建立 数据传输 连接释放
客户端服务器方式
主动发起: 客户端 被动等待:服务器
连接建立 - 三次握手
发送请求 - 建立连接 - 确定建立连接
本质是数据报
seq 是自己的序号位
ack 是期待对方的序号为
第一步:
Client 向Server发送建立连接请求(连接请求报文段)
SYN 同步位: SYN =1 连接请求
seq 序号位 seq = x (Client的序号,随机值,此时设为x);
第二步:
Server向Client发送确认信息(确认报文段),并且为TCP连接做准备(分配缓存和变量)
SYN = 1 同步中
ACK = 1 确认位有效 ack 确认号字段有效
ack =x+1 接受想要收到的来自Client的下一个字节(x+1)
seq = y (server的序号)
第三步 Client为该TCP连接分配缓存和变量并向服务器发送确认收到对方的确认
SYN = 0
ACK = 1 ack = y+1;
sqe = x+1;
连接建立完毕
接下来 传输数据
连接建立产生的问题 - SYN洪泛攻击
核心: 光发送第一步连理连接的请求SYN,此时Server回给予Client回应,我恶意的不回应Server,并且持续的发送建立连接请求SYN, 导致服务器建立不了连接还得花大量资源来应答我
解决SYN洪泛攻击 - SYN cookie
数据传输
连接释放 - 四次握手 - 两次关闭
一次是Client发出的 一次是Server发出的
发送请求 - 释放连接
第一步:
Client向Server发送停止的请求 (连接释放报文段)
FIN 结束位: FIN=1;
seq = u; //报文段第一个字节的序号
第二步:
Server向Client回复一个确认收到ACK,并且释放Client到Server这一段的连接(半关闭)
ACK = 1;
seq = v;
ack = u+1;
注意:此时Server到Client的还没关闭
第三步: ⭐
Serve向Client发送停止的请求 (连接释放报文段)
FIN = 1;
ACK =1 ;
seq = w;
ack = u+1;
注意;第二步的ack = u+1 和 第三步的ack = u+1
个人理解: 因为在第二步到第三步过程中 Client并没有发送数据,此时仍然是u,所以Server期待的下一个字节仍然是u+1
而第二步到第三步的时候,Server发送了停止请求(连接释放报文段) ,假设发送完后,自己的序号为变为w ,则推理出该报文段大小为w-v
第四步:
Client 回复 收到,然后等待计时器设置的时间后,彻底关闭TCP连接
ACK = 1;
seq = u+1
ack = w+1;
TCP可靠传输
传输层: TCP实现可靠传输,或者利用UDP+应用层 尽可能传输
网络层: 尽可能的去交付数据
校验 - 增加伪首部
跟UDP校验一样, 发送方和接受方 增加伪首部 二进制反码求和 判断是否发生错误
序号
传输的报文段大小 取决于 MTU
确认
确认机制 : 发送方确认接受方已经收到了数据报
发送一个确认报文段
已发送 123 那么 确认报文段首部确认号为4,
Server表示 : 我已经接受123,接下来你是要给我发送4是吗
等到确认报文段到达发送方的时候,经过确认,这个时候才把已经发送出去的123报文移出TCP缓存
接下来发送456 和 78 报文段
采用的是累计确认
所以 当456 丢失的时候
返回的确认报文 首部报文序列还是 4 ,发送方会重新发送 456 - 重传机制
重传
确认重传不分家
超时重传
TCP自适应算法- 动态改变重传时间RTTs(加权平均时间)
保证超时时间设定的时候,不会过长也不会过短
超时重传得一直等 ,时间过长,有没有办法在超时时间之前就知道接受方有没有丢失报文段并且进行重传呢
冗余ACK(冗余确认)
我想要2号报文段,但是你给我传的3号 这就是一个冗余报文段
当冗余报文段达到一定数量,我就可以确定 我要的报文段丢了
那就重传吧
链路层的滑动窗口协议,停等协议,GBN协议,SR协议等 在传输层都会用到
TCP流量控制 ⭐ - 发送方发慢点 - 滑动窗口
流量控制 : 发送方发慢点,让接受方来得及接受
接受方 根据接收缓存的大小
动
态
的
调
整
发
送
窗
口
大
小
\color{red}{动态的调整发送窗口大小}
动态的调整发送窗口大小 = 接收窗口rwnd (receive window)
接收窗口将rwnd通知发送给发送方
接受方如何动态调整发送方的窗口大小呢?
设置报文段中的窗口字段, 相当于告诉发送方我可以接受的数据大小是多少
发送窗口大小 取决于接收窗口rwnd +拥塞窗口cwnd 的最小值
举例说明
TCP是累计确认机制,不是发个报文段等接手后再发送下一个的停等协议
连续发送多个报文段
初始滑动窗口为400.每100位一格
后来滑动窗口为3格,1格,0格动态改变
滑动窗口为0 ,此时进入了等待
等把所有数据上传到应用层以后,
继续传输的话, 发送方会再发4格的滑动窗口
设计了持续计时器 ,用来检测报文段是否丢失
TCP拥塞控制 - 四种算法 ⭐
拥塞是一个主机造成的吗?
并不是,是多个主机造成的,求资源需求 > 可用的资源
堵不如疏
四种算法
前提条件:
1.假定单方向传送
2.接受方总是有足够大的缓存空间,根据拥塞程度动态的调节发送窗口大小
因为 发送窗口 = min{接收窗口,拥塞窗口}
发送窗口: 发送方设置 - 网络当前容量
接收窗口 : 接受方设置 - 接受方容量
慢开始+拥塞避免
当不拥堵的时候(第一轮),发送x个 发现还是不堵(第二轮) 发送2x个
一个传输伦次 = 一个往返时延RTT
慢开始状态 -> 拥塞避免状态
慢开始状态 : 指数级增长 *2
达到ssthresh - 慢启动阈值
拥塞避免状态: 线性增长 +1
因为报文段发的太多, 会导致拥塞 所以拥塞避免状态拥塞窗口增加减慢