IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 运输层协议 -> 正文阅读

[网络协议]运输层协议

如何优化TCP 协议,来达到好的效果

在这里插入图片描述
左面主机想和右面主机进行通讯
在应用层:进程主体,申请端口,创建套接字(一个四元组),两端的套接字和套接字进程通讯。
在运输层:端到端:防火墙
在网络层:主机和主机之间的(IP 和 IP 之间)

运输层协议概述:
TCP :传输控制协议,面向连接,可靠的数据传输协议。
UDP :用户报协议,无连接,不可靠的数据传输协议。
交付和差错检验是TCP / UDP 最低责任。
基本责任,将两个运行在端上的进程之间负责通信。

UDP 为什么要进行差错检验?
对于可靠还是不可靠,讲的是,包到的顺序,有没有丢包,UDP 并不管理丢包。
不过一个包经过一系列过程中,到达对端,还是要进行差错检验的。
差错检验:奇偶校验。。。
有问题的数据丢掉,没有问题的数据交付。
有差错的包是否可以恢复?只要加的校验码足够多,就可以。

所谓的连接,并不是真的有一个线,将两个对象连在一起,而且两端上各自有一个数据,来存储对方的数据,知道对方的变化。

对于UDP ,不需要知道对方的状态。发送的时候不知道对方是否还在线,如果对方不在线的话,UDP 依然会发送数据,这就给网络带来了一定的压力,所以使用UDP 的时候,需要在应用层,做一个封装。所以对于网络来说,UDP 是不友好的。

多路复用,多路分解:
当一个地址收到很多消息,到了之后,需要分发信息(多路分解)。
每个端口发送的信息,都经过这一个地址(多路复用)。

多路复用和多路分解
在这里插入图片描述
在运输层,只关注端口。
在网络层,只关注从哪里来的,到哪里去。

在这里插入图片描述
一个网站服务端,两个客户。
客户A, 发送一个报文,四元组
客户C,发送两个报文,开了两个客户端,在C 中也有一个26145 的端口,但是对于服务端来说,这还是3个客户,虽然房间号一致,但是楼号不一致。

为什么会选择无连接的运输服务 UDP

  1. 关于何时、发送什么数据的应用层控制更为精细(使用TCP ,发送数据,不受自己控制,即使自己发送太快,TCP 也会根据自己流量控制,拥塞控制,发送数据。UDP, 没有这个限制)
  2. 无需建立连接(代价小,效率高)
  3. 无状态连接(负担小)
  4. 分组开销小(每一个包的真实信息承载量更大)

SNMP 简单网络管理协议
所有网络提供商,管理光猫。
在网络不太顺畅的时候,TCP 会限制发送,使用UDP 就像是一个法外狂徒,可以全力使用网速,虽然可能会对网络造成更大的阻塞(TCP 更加抑制),这个时候,需要管理网络,限制发送端的流量,尽可能限制UDP 发送,虽然也限制了TCP。
在网络中发生了网络风暴(形成死循环的情况,可能是路由表出现问题,或者是DNS 层面发生问题,导致信息一直在内部循环,数据会越来越多,导致TCP 连接无法建立),这个时候管理网络,只能使用UDP,发送很多的包,有一个到达一个路由器,就会组织风暴的发生。
在这里插入图片描述
UDP 采用的是循环冗余校验。

UDP 校验和
在这里插入图片描述
先对所有的相加,看最后一组,发生了溢出,溢出的1与原本相加得到的后两位01 相加,得到了10,每次相加都这样循环,最终得到校验码。

如何构建一个可靠的连接。

方法1 : 使用一个可靠的信道。(运输层传输为可靠,TCP)
当使用一个不可靠的信道,我们需要做哪些事情,让不可靠的信道,变得可靠。

在写一个大型应用的时候,我们应该需要考虑,我们需要使用什么。

RDT 1.0: 完全可靠的信道
在这里插入图片描述
发送方:拥有完全可靠的信道,创建一个数据包,使用UDP 发送包就可以
接收方:可靠的接收信息,解析包,上传数据即可。

RDT 2.0 : 具有比特差错信道。传递的信息不会丢失。
在这里插入图片描述
在这里插入图片描述
客户端要发送数据,下层先将数据和产生的校验和封装成一个包,然后将这个包用UDP 发送出去,接收方下层,收到这个包之后,进行冲突检测,如果检测发成冲突,接收方封装一个NAK 的包,然后发送过去,如果检测之后,没有发生冲突,那么解析这个包,然后将包中的信息传给上层,并且封装一个ACK 的包,用UDP 发送给客户端。
返回客户端,如果这个时候收到了发送方发送的包,并且检测到有NAK 的包,那么UDP 重发数据,如果检测到有ACK 的包,那么进行下一次的数据传输。

这都基于发送的信息不会丢失,但是效率过于慢,等待的过程有点长。每一次往返周期只有一个包,信息量很大的时候,会很慢。

RDT 2.1
在这里插入图片描述在这里插入图片描述
因为rdt 2.1 一次只能发一个包,为了提高效率,我们使一次可以发多个包。
这个先假定为两个包(0包, 1包)
发送方想要发送0包,下层先将0这个序号和数据以及校验码 进行封装,发送数据
发送方想要发送1包,下层先将1这个序号和数据以及校验码 进行封装,发送数据

接收方,需要的不仅仅是包的正确性,还要保证包的序列是正确的。
所以等待0 / 1的接收方如果收到冲突的包,封装NAK 以及校验和
如果收到的包没有冲突。
当等待0的接收方收到0的包,会解析包,然后向上层发送数据,并且,封装ACK, 和 校验码 包,然后向发送方发出,然后等待1包
当等待0的接收方收到1的包,封装ACK, 和 校验码 包,然后向发送方发出,并继续等待0包。

当等待1的接收方收到1的包,会解析包,然后向上层发送数据,并且,封装ACK, 和 校验码 包,然后向发送方发出,然后等待0包。
当等待1的接收方收到0的包,封装ACK, 和 校验码 包,然后向发送方发出,并继续等待1包。

接着回到发送方,
等待ACK或NAK0 的一端,如果收到包,但是包有冲突,或者包是 NAK ,那么重新发包
等待ACK或NAK0 的一端,如果收到包,但是包没有冲突,并且包是 ACK ,那么等待1的调用

等待ACK或NAK1 的一端,如果收到包,但是包有冲突,或者包是 NAK ,那么重新发包
等待ACK或NAK1 的一端,如果收到包,但是包没有冲突,并且包是 ACK ,那么等待1的调用

RDT 2.2
在这里插入图片描述
在这里插入图片描述
RDT 2.2 中去除了NAK 只有ACK, 只确认我收到的东西,没有收到的东西,不去确认。

发送方:
等待发送0的发送方,想要发送消息,下层封装 ** 0 **, 数据校验和, 然后通过udp 发送数据。
等待发送1的发送方,想要发送消息,下层封装 ** 1 **, 数据校验和, 然后通过udp 发送数据。

接收方:
等待来自0的信息,如果收到了包,并且没有错误,并且是序号0,那么会先解析包,然后上传数据,然后封装 ACK0校验和,发送包回去。
等待来自0的信息,如果收到了包,并且没有错误,但是序号是1,那么会封装 ACK1校验和,发送包回去。

等待来自1的信息,如果收到了包,并且没有错误,并且是序号1,那么会先解析包,然后上传数据,然后封装 ACK1校验和,发送包回去。
等待来自1的信息,如果收到了包,并且没有错误,但是序号是0,那么会封装 ACK0校验和,发送包回去。

回到发送方:
等待ACK0 的,如果收到了包,但是,包错误,或者ACK 序号是1,那么重新发包
等待ACK0 的,如果收到了包,包没有错误,并且ACK 序号是0,那么等待1

等待ACK1 的,如果收到了包,但是,包错误,或者ACK 序号是0,那么重新发包
等待ACK1 的,如果收到了包,包没有错误,并且ACK 序号是1,那么等待0

所以包出错,发送上一次包的 ACK

RDT 3.0
在这里插入图片描述
在rdt 2.2 上增加一个一个定时器。

发送方想要发送一个0号信息,会先封装一个0数据校验码 ,然后发送这个包,并且开始一个计时器。
如果收到一个包,包有错误,或者收到的ack 是 1,那么什么也不做。
如果时间结束,那么重新发送消息,并且重新开始计时器。
如果收到包,并且包没有错误,并且收到的ack 是0, 那么停止计时器。
等待发送的过程中,如果收到包,那么什么也不做(交给超时处理)
1 方同理。
当前这个协议,依然存在的问题,序号太少,如果收到上一次的0 / 1 的消息,那么会出现bug

TCP 中,第一次发送的序号是随机生成了,然后后面的序号跟随前一个序号增加1,序号都不是从0开始的,所以获得冲突的信号可能性很小。
TCP 中:

  1. Go-Back-N 协议,返回的ack 值是最后收到的包的ack ,说明我要收的包是这个ack 下面的那个包。如果一次发出很多的包,如果有一个包被劫持了,那么序号后面的包都会被退回来。
  2. 选择重传法:发送很多包,然后有一个包丢失,那么会返回丢失包的序列,并且其他的包不会回退。
  3. 流量控制:每次发送包之后,返回的信息,会包含接收端的空闲窗口的大小,下一次发送空间窗口大小的数据。如果空间窗口大小为0,那么下一次会发送一个空包。(通过两个缓冲区的窗口的交互)
    send 函数做的事情,其实是将信息放到发送缓冲区中。

在这里插入图片描述

TCP 协议

在这里插入图片描述
应用层和运输层接口:套接字
通过套接字可以使用底层提供的网络服务。

TCP 报文结构

在这里插入图片描述
宽 32 bytes
所以最大端口号为16字节为 65535
序号是这次发的TCP 字节流序号,假如发1000,下次就是2000, 不是连续的
确认号是期望得到的下一次得到的包号,这次发1000,会的序列号是2000
序号最大32位
首部长度4 为 4bytes, 单位是32字
接收窗口:目标的空余窗口大小,当接收窗口为0,下一次会发一个空包过去。
特殊标志位:
URG : 紧急数据
PSH :立即上交(收到这个数据,直接上交给应用层)
! ACK :确认码,如果ACK 为 1 ,说明,包中不包含数据,是对方给我的一个确认,是ACK 包
RST :连接远程服务器,发生ConnectionReused 就是 回应一个 RST,端口没有监听。
!SYN :三次握手,第一次握手发送,第二次握手收到,是用来建立连接的
!FIN : 四次挥手的
因特网校验和:确保数据是正确的。

TCP 在远程主机上,按一个x,到 x 显示会发生什么事情?
从本地到键盘感知,驱动程序,内核拿到,内核查被谁打开了,然后给响应的应用,然后把x 封装成数据包,发送到远程的云主机,本地收到数据包和ACK ,显示x,再显现出来。
ACK 是对上一次服务器发送的确认。
第一次发送序列号 731, ACK 是 1024,所以回下次期望收到732(ACK 是 732),序列号是前一次的1024, 然后本地回Seq 732, 期望下一次发送1025(ACK期望下一次发送)
在这里插入图片描述
往返时间估算:
A 包 发送到 B 服务器,然后再传回来?
SampleRTT : 样本往返时间,单次发送包到对面,收到ACK
EstimatedRTT : 估算往返时间
公式
EstimatedRTT = (1 - α) ? * ? EstimatedRTT + α ? * ?SampleRTT α = 0.125
Dev = (1 - β) * DevRTT + β * |SampleRTT - EstimatedRTT| ? β = 0.25
TimeoutInterval = EstimsedRTT + 4 * DevRTT
第一个RTT 根据估算时间和往返时间的差值来计算
网络应该处于一个比较稳定的,出现一个短暂的波动,不应该算异常
但是一直时间不好,时间状态就会被刷上去,回拿到一个客观的超时时间,有一次出现波动,不会影响计算超时时间(引申到网络监测变化)
但是持续时间很长,应该可以作为参考。
所以网络超时时间是动态的,当超时的时候,会把超时时间加倍,避免因为网络突变,导致时间边长。
如果不调整,回导致很多包在网络上跑

在这里插入图片描述
流量控制
整个TCP 有一个发送缓冲区,和接收缓冲区
recvbuff 值是一定的
接收窗口的值,是上一次收的 减去 上层应用读走的,得到的也就是接收缓冲区。
上次发走的数据,减去上次ACK 的数据,(数据还在网络中的数据)应该小于等于 接收窗口的大小。
才能保证数据不被丢失,如果接收窗口满了,还发,会导致数据丢失。
流量控制针对发送双方,如果网速不好,流量控制机制给网络有优化有限。但也会抑制发送速率

网络不好,也就是现在在网络中的数据增多,未交付的数据增多。

流量控制更多针对的是发送方

在这里插入图片描述

三次握手

需要记住的是:
三次握手每次发送的都是什么?
TCP 三次握手,由客户端发起,服务端堵塞在accept 那里,
第一次:客户端发送SYN = 1 信息
第二次:服务端发送SYN + ACK = 1 的信息
第三次:客户端回SYN = 0, ACK = 1;
为什么是三次握手,而不是两次握手?
在发起方,知道,我发的消息,服务方可以知道,服务方发的消息,我也可以收到
在服务方,知道,我能收到客户方的消息,我的消息客户方也知道
如果变成两次握手,也就是不要最后一次握手。
这样对客户方没有影响,服务方不知道我发的消息能否被收到。是不可以少的
四次握手是可以的,但是三次握手就已经可以了,但是发的消息出现冗余的情况。
三次握手的目的就是为了通讯。

在这里插入图片描述

四次挥手

发起方先说再见,被动方回复。
被动方说再见,发起方回复。

四次挥手,为什么要4次?
只挥1次是否可以?

  1. 主机A 发起结束,本地调用close, 发送一个FIN 包
  2. 被动方收到SYN 知道要结束,然后回复一个ACK 说知道停止。
  3. 至于能不能分手,还是需要看被动方。
  4. 服务端可以选择不分手,但是这个时候,会出现异常情况,出现的情况是半连接情况。这个时候连接,实际上还在,发起方等待SYN ,这种情况会发生一个有害的套接字,这样会出现,一个进程维持很多个已经断开的连接,所以需要回复一个SYN
  5. 发起方实际上需要等待20s~30s 这一个周期。

(为什么要等待?)

  1. 对方的ACK 会丢失,服务端会多次发SYN ,等待会避免SYN 丢失。
  2. 等待这么多时间,是避免刚断开连接,另外一个进程占用端口,收到上一个进程中遗留的包。
    (假如上一个服务端发送多个FIN有一个很久才过来,会有结果导致,刚建立的连接,就关闭。)

在这里插入图片描述
TCP 状态转换序列

在这里插入图片描述
客户端:
默认状态为Close 序列,
调用connect 发送 SYN ,接收SYN ACK 发送ACK 进行建立连接。
关闭发送FIN
到 FIN_WAIT_1
接收到ACK
到 FIN_WAIT_2
接收FIN 发送 ACK
TIME_WAIT
等待2ms

在这里插入图片描述
服务端:
默认Close
然后bind
开始监听 Listen
接收SYN 发送SYN ,ACK
到SYN_RCVD 接收ack ,这个时候可能会有数据
到 ESTABLSHE
接收FIN 发送 ack
(!)CLOSE_WAIT (这个时候是要关闭,等着自己关闭连接)
发送FIN
(!)LAST_ACK
接收ACK ,不发送

  1. 洪泛攻击,只进行两次连接
  2. 全部都在close wait, 导致很多半连接
    这两种情况都会使程序崩溃。

拥塞控制方法:
如何通过协议方式,减少当网络延迟过高,波动,链路断开之后,数据暴增。
拥塞控制:

  1. 端到端的控制
    TCP 使用超时,三次冗余ACK ,然后减少接收窗口
    发生超时,超时时间加倍
  2. 网络辅助的拥塞控制

ATM网络
ABR 拥塞控制
在这里插入图片描述

把数据包分为数据信元,和资源管理信元。
在数据信元中夹杂着资源管理信元,看路上是否发生了拥塞,资源管理信元过去之后,还会回来,来上告路上的情况。
资源管理信元:

  1. 显示拥塞指示:EFCI (1bit)如果网络发生拥塞,这个置为1,当发送方收到这个,就会减少发送。
    这个比特,可以被任何一个交换机将其拥塞指示设为1。当收到的信元多数为1,则认为链路拥塞,改变CI
  2. 无增长比特NI ,显示轻度拥塞,经过每一个交换机,会更新er,目的是找到网络的吞吐量。
    找到最低的,就是吞吐量。

多个微服务并发,可以使用这个策略,来看哪个吞吐量最低。

TCP 拥塞控制
rcwd 用来做流量控制的
cwnd 拥塞窗口
上次发送的 减去 上次接收到的 <= {cwnd, rwnd}
在这里插入图片描述
TCP 拥塞控制的知道思想

  1. 一个丢失的报文段意味着拥塞,丢包就应该减小发送端的发送速率。(有一个丢了,就说明有问题)
  2. 一个确认的报文段表示网络正在向接收方交付报文段,因此,当收到对之前的报文段的ACK 后,应该增加发送方的速率。
    一个正确的确认,表示正在交付报文,收到ACK 就是正向的激励,让发送速率稳定,健康
  3. 带宽探测
    试探网络能容纳多少,每次都去试探,尽可能多发,收到确认继续尝试,发现丢包之后收敛,直至一个稳定值

拥塞控制之慢启动
在这里插入图片描述
MSS 最大报文长度。
最开始是一个MSS, 每收到一个确认,增加一个。
1 -> 2 -> 4 -> 8 …
当发生超时的时候,假设8超时,cwnd 设为 4MSS
然后新的cwdn 大于等于 4MSS 的时候,进入平缓模式

拥塞避免模式
在这里插入图片描述
慢启动,指数级增长,拥塞避免线性增加。
出现超时。重新开始慢启动,阈值为当前一半。

在这里插入图片描述
出现快速恢复,说明有冗余ACK ,
冗余ACK说明只是这一个包的问题
超时说明后面的包都没有到
ssthresh 阈值需要设置。

超时:慢启动。
冗余ACK 迅速恢复。
大于等于阈值:拥塞避免。

在这里插入图片描述

初始状态,初始状态为1 ,阈值设为64kb,冗余ACK = 0,
当收到一个冗余ACK ,冗余ACK ++,收到一个新的ACK 的时候,cwnd += MSS,冗余ACK 清0,发送新的报文段
当cwnd >= 阈值,进入拥塞避免模式
每收到一个ACK, cwnd = cwnd + MSS * (MSS / cwnd) 线性增长,冗余ACK 清0, 发送新报文
收到冗余ACK ,冗余ACK ++
如果冗余ACK == 3, 那么阈值设为cwnd一半, cwnd 设为阈值 + 3 * MSS(有三个冗余ACK)
进入快速恢复
没收到一个冗余ACK ,cwnd += MSS
收到新的ACK cwnd = 阈值, 冗余ACK = 0到拥塞避免
所有的模式下发生超时都会进入到慢启动
慢启动下如果冗余ACK == 3 ,进入到快速恢复状态

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-10-07 14:09:39  更:2021-10-07 14:11:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:40:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码