文章目录
OSI 和 TCP/IP 模型在传输层定义两种传输协议:TCP(或传输控制协议)和 UDP(或用户数据报协议)。
TCP/UDP协议:
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而UDP则不为IP提供可靠性、 流控或差错恢复功能。一般来说,TCP对应的是可靠性要求高的应用,而UDP对应的则是可靠性要求低、传输流量大,传输速度快的应用。
- TCP支持的应用协议主要 有:Telnet、FTP、SMTP等;
- UDP支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、DNS(主域名称系 统)、TFTP(通用文件传输协议)等.
TCP/IP协议与低层的数据链路层和物理层无关,这也是TCP/IP的重要特点
数据的传输建立在网络层之上, 但是网络层是不可靠的, 他不关心数据是否已经正确到达对端, TCP 是建立在不可靠传输上的可靠协议
TCP与UDP区别:
- 概述:
UDP的设计比TCP晚,只是去掉了可靠性
-
面向连接vs无连接
TCP 有三次握手的连接过程,UDP 适合消息的多播发布,从单个点向多个点传输消息(广播) -
可靠性
TCP利用校验和,超时重传,seq ,ack,滑动窗口,流量控制等机制来保证可靠性;UDP尽最大努力交付,即不保证可靠交付 -
TCP面向
字节流
,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文
的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议,在线视频媒体,电视广播,多人在线游戏等) -
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
-
UDP 一个 socketfd(不存在线程安全的问题) ,TCP 多个 socketfd(多个线程如何处理)
-
UDP 一个sendto 对应一个recvfrom ,不然就丢包
何时使用UDP:
- 你真的很在乎延迟,不能忍受重传,那么就用UDP,例如 NTP 协议。
重传NTP消息纯属添乱。
- 你真的不在乎可靠性,丢一些包也不需要重传,那么就可以用 UDP。例子我想不出来。有人说音频或视频流可以用UDP,不过据我看来各大视频网站都用HTTP协议,而HTTP是基于TCP的。
- 你需要NAT穿透,那么不得不用UDP。
- 其他情况,一旦程序要自己做重传,你都是在用UDP模拟出蹩脚的TCP,还不如直接用TCP呢。
总之:使用 UDP 需要有强大到不容置疑的理由,when in doubt, use TCP.
UDP不好控制用完网络带宽
我的思考:
连接自然不用多说,可靠性主要还是靠下文的这些保证的:
- 校验和(下文略)
seq
与ack
(下文略)- 超时重传(下文略)
- 滑动窗口
- 流量控制
- 拥塞控制
下面一个一个来讲:
滑动窗口
接收方:ACK 里的重要信息
我们也说过 TCP 是靠 ACK 来做到可靠传输的, 没有收到 ACK 就重发, 那么这个 ACK 里包含了两个重要的信息 :
- 期望收到的下一字节的序号, 假如 A 收到了对方发来的 1~100 字节的数据, 那么他回复的 ACK 里包含的序列号就是 101, 而这个时候如果 A 收到了不是第 101 字节数据的时候, 他是不会回复对应的 ACK 的, 假如收到了 102~202 字节的数据, 是不会回复序列号为 203 的 ACK 的, 而是继续发送序列号为 101 的ACK
- 当前窗口大小, 自己现在能够接受的窗口的大小.
发送窗口示意图
如上图是一个从 3~7 字节的滑动窗口, 窗口大小为 3 字节
第 3 字节已经被确认 (收到了 ACK), 可以被释放掉了, 而第 7 字节已经准备好了但还不能发送, 因为还没有进入"窗口"
滑动窗口是动态的, 在下一刻我们可能收到了第 4 字节的 ACK, 于是窗口右移一个分组, 这时第 7 字节就能发送了
窗口大小和TCP协议栈中缓冲区的关系
我们知道, 在 send 和 recv 端都有发送缓冲区和接收缓冲区, 而你的进程读写数据都不是发送给对方, 或者从对端拿到的, 都是拷贝入发送缓冲区里, 或者从接收缓冲区中拷贝出来的,
以发送缓冲区为例, TCP 协议栈里有一个 buffer 来作为每个 TCP 套接字都拥有的一个发送缓冲区, 你 send 的数据是先拷贝进入这个缓冲区, 并不是直接就发送到对端了
在判断 send 是否成功发送的时候只能判断的是 send 成功返回(在成功拷贝数据进入缓冲区后返回
), 我们只能将数据成功全部拷贝进入发送缓冲区当做成功发送的标志, 其实还没有
而 TCP 滑动窗口的大小实际上就是接收缓冲区大小的字节数
提问:滑动窗口是如何保证分组无差错、有序接收的呐?
看上面一句话"假如收到了 102~202 字节的数据, 是不会回复序列号为 203 的 ACK 的, 而是继续发送序列号为 101 的ACK",再看上面的那副图!!也就是说ACK不会乱,而发送方会按照ACK的确认来移动滑动窗口.
流量控制
什么是流量控制以及如何实现?
如果发送者发送数据过快,接收者来不及接收,那么就会有分组丢失。为了避免分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。流量控制根本目的是防止分组丢失,它是构成TCP可靠性的一方面。
由滑动窗口协议(连续ARQ协议)实现。滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。
流量控制引发的死锁?怎么避免死锁的发生?(OS没有复习,还不敢提到这个)
当发送者收到了一个窗口为0的应答,发送者便停止发送,等待接收者的下一个应答。但是如果这个窗口不为0的应答在传输过程丢失,发送者一直等待下去,而接收者以为发送者已经收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁。
为了避免流量控制引发的死锁,TCP使用了持续计时器。每当发送者收到一个零窗口的应答后就启动该计时器。时间一到便主动发送报文询问接收者的窗口大小。若接收者仍然返回零窗口,则重置该计时器继续等待;若窗口不为0,则表示应答报文丢失了,时重置发送窗口后开始发送,这样就避免了死锁的产生。
拥塞控制
拥塞控制和流量控制的区别
- 拥塞控制:拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网 络负载过大的情况;常用的方法就是:( 1 )慢开始、拥塞避免( 2 )快重传、快恢复。
- 流量控制:流量控制是作用于接收者的,它是控制发送者的发送速度从而使接收者来得及接收,防止分组丢失的。
拥塞控制的算法
我们在开始假定:1、数据是单方向传递,另一个窗口只发送确认;2、接收方的缓存足够大,因此发送方的大小的大小由网络的拥塞程度来决定。
(1)慢开始算法(cwnd,一个 RTT 时间,拥塞窗口大小翻一倍)
发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。
慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
这里用报文段的个数作为拥塞窗口的大小举例说明慢开始算法,实际的拥塞窗口大小是以字节为单位的。如下图:
从上图可以看到,一个传输轮次所经历的时间其实就是往返时间RTT,而且每经过一个传输轮次(transmission round),拥塞窗口cwnd就加倍。
为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法如下:当cwnd<ssthresh时,使用慢开始算法。
当cwnd>ssthresh时,改用拥塞避免算法。
当cwnd=ssthresh时,慢开始与拥塞避免算法任意
注意,这里的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,然后逐渐增大,这当然比按照大的cwnd一下子把许多报文段突然注入到网络中要“慢得多”。
(2)拥塞避免算法(cwnd,一个 RTT 时间,拥塞窗口大小+1,而不是前面的翻倍了,拥塞时将ssthresh设置为一半,cwnd=1开始翻倍(乘法减小),cwnd=1开始+1(加法增大))
无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
(1)拥塞窗口cwnd初始化为1个报文段,慢开始门限初始值为16
(2)执行慢开始算法,指数规律增长到第4轮,即cwnd=16=ssthresh,改为执行拥塞避免算法,拥塞窗口按线性规律增长
(3)假定cwnd=24时,网络出现超时(拥塞),则更新后的ssthresh=12,cwnd重新设置为1,并执行慢开始算法。当cwnd=12=ssthresh时,改为执行拥塞避免算法
(3)快重传算法(发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段)
快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(与滑动窗口有异曲同工之妙)(为的是使发送方及早知道有报文段没有到达对方,可提高网络吞吐量约20%)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期(超越超时重传)。如下图:
(4)快恢复算法()
快重传配合使用的还有快恢复算法,有以下两个要点:
- 当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半(为了预防网络发生拥塞)。但是接下去并不执行慢开始算法(翻倍)
- 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh减半后的值,然后执行拥塞避免算法(+1),使cwnd缓慢增大。如下图:TCP Reno版本是目前使用最广泛的版本。
注意:在采用快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用
总结一下(能记住的):
慢开始:cwnd 翻倍
拥塞避免:减半,+1
快重传:三个确认,立即重传未收到的报文
快恢复:cwnd 变为ssthresh减半后的值,拥塞控制(+1)
https://blog.csdn.net/weixin_36888577/article/details/84641912