文章目录
UDP 和 TCP 的特点
UDP
用户数据报协议 UDP(User Datagram Protocol):
1.是无连接的;
2.尽最大可能交付;
3.面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部);
4.没有拥塞控制;
5.支持一对一、一对多、多对一和多对多的交互通信;
6.UDP的首部开销小。
TCP
传输控制协议 TCP(Transmission Control Protocol)是
1.面向连接的;
2.每一条 TCP 连接只能是点对点的(一对一);
3.提供可靠交付,有流量控制,拥塞控制;
4.提供全双工通信;
5.面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块)。
TCP 的三次握手
三次握手的过程
上图中,A为客户端,B为服务器。
1.初始状态时B创建了传输控制块并处于监听状态,A处于关闭状态;
2.A要连接了,主动打开连接,并发送请求到B,SYN=1,ACK=0,序号为任意一个x,确认号为任意一个a;(A,x,a)
3.B收到请求,发送报文,SYN=1,ACK=1,序号为y,确认号为x+1;(B,y,x+1)
4.B收到A发过来的,发送报文,SYN=0,ACK=1,序号为x+1,确认号y+1,(A,x+1,y+1)
A最后为什么还要再发一次确认?
防止已经失效的链接请求报文段突然又传到了B。如果不用三次握手,例子如下:
1.A发了请求a1,a1请求丢了,没收到确认;
2.A重传再发送请求a2,B收到了a2,建立连接,并且传输成功,然后释放了连接;
3.请求a1突然出现,B收到了,B认为连接成功了,然后等A发数据,但A不会理会,于是这样浪费了很多B的时间。
TCP 的四次挥手
TCP四次挥手的过程
1.B需要的数据A已经全给它了,并且已经确认了,A提出连接释放请求a1,FIN=1,seq=u;(A:FIN-WAIT-1,B:ESTAB-LISHED)
2.B收到请求a1,并确认,发送确认报文b1,seq=v,ack=u+1;(A:FIN-WAIT-1,B:CLOSE-WAIT)
3.A收到B发送的b1,确认后,进入状态FIN-WAIT-2,等待B发出连接释放报文;(A:FIN-WAIT-2,B:CLOSE-WAIT)
4.B要发给A的数据发送完毕了,B发出请求释放连接b2,FIN=1,seq=w,ack=u+1
;(A:FIN-WAIT-2,B:LAST-ACK)
5.A收到b2,确认,发出a2,ACK=1,seq=u+1,ack=w+1,,进入TIME-WAIT;(A:TIME-WAIT,B:LAST-ACK)
6.B收到a2后,直接CLOSED,A则是需要再经过2MSL时间进入CLOSED;(2MSL-CLOSED,B:CLOSED)
为什么A在TIME-WAIT状态要等待2MSL的时间?
有2个原因:
1.考虑A最后一次发送的a2报文丢失了,那么B会一直在LAST-ACK状态等A的信号,时间长了,B会超时重传b2信号。A会在2MSL时间内收到重传的b2信号,这样让B能正常进入CLOSED状态;
2.经过2MSL的时间,本次连接的时间内的报文都会从网络中消失,这样下次的连接就不会有这次报文的干扰。
四次挥手的原因
客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。
TCP可靠传输的实现
TCP 滑动窗口
窗口用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。
发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。
如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;
接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。
超时重传时间选择
两个公式:
- 一个是加权平均往返时间
R
T
T
s
RTT_s
RTTs(Round-Trip Time)的更新公式:
R T T s = ( 1 − α ) × ( R T T s ) + α × R T T , ( 0 ≤ α < 1 ) RTT_s=(1-\alpha) \times(RTT_s)+\alpha \times RTT ,(0 ≤ \alpha< 1) RTTs=(1−α)×(RTTs)+α×RTT,(0≤α<1)
α \alpha α的推荐值为0.125。 - 另一个是超时时间
R
T
O
RTO
RTO 的计算:
R T O = R T T s + 4 × R T T D RTO=RTT_s+4\times RTT_D RTO=RTTs+4×RTTD
R T T D RTT_D RTTD为偏差的加权平均值。它的计算规则如下:
R T T D = ( 1 − β ) × R T T D + β × ∣ R T T s − R T T ∣ ( 除 第 一 次 ) RTT_D=(1-\beta)\times RTT_D+\beta\times\left| RTT_s -RTT\right| (除第一次) RTTD=(1−β)×RTTD+β×∣RTTs−RTT∣(除第一次)
R T T d RTT_d RTTd第一次计算时候直接取 R T T RTT RTT的一半。 - 超时重传后的
R
T
T
s
RTT_s
RTTs计算
Karn算法
选择确认SACK
-
解决的问题:
一个报文中,字节块1-1000收到了,1001-1500没有收到,1501-3000收到了,3001到3500没有收到,3501-4500收到了。为了让服务器只重传没有收到的1001-15–,以及3001-3500,而不需要重传其他的数据。 -
解决的方式
1.在建立TCP连接时候,在TCP首部的选项中加上“允许SACK”
2.一头一尾来指明一个缺失的字节块边界,一个字节指明SACK选项,一个字节指明这个选项要占用多少字节
由于SACK并没有明确指明发送方需要怎样响应SACK,大多数的实现还是重传所有未被确认的数据块。
TCP流量控制
流量控制的定义
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接受。
利用滑动窗口实现流量控制
实现滑动窗口中,发送方的发送窗口不能超过接收方给出的接受窗口的数值。
TCP的传输效率
为了传送一个字节的数据,要附加上40字节的ip头部,效率会降低很多。
解决方式:适当推迟发送确认保温,并尽量使用捎带确认的方法。
具体实现:TCP中使用Nagle算法。
糊涂窗口综合症:
1.TCP接收方的窗口有了很小的空位置就发送确认,让发送方发送数据;
2.TCP发送方收到这个确认,立刻又发送1字节数据;
3.上面1,2两步相互循环,网络传输效率一直很低。
解决方式:接收方空位置多了再发送确认;发送方数据多了再发送数据。
TCP拥塞控制
概念
- 拥塞控制的概念
防止过多的数据注入网络,避免网络中的路由器或链路过载。 - 与流量控制的区别
流量控制是点对点的通信量控制,研究对象是链路终端的 两个主机,而拥塞面向整个网络链路。
拥塞控制的四个算法
四个算法是:慢开始、拥塞避免、快重传、快恢复。
在拥塞控制算法中,讨论的窗口的单位是报文,而TCP的流量控制中讨论的单位是字节。
1.慢开始与拥塞避免
发送的最初执行慢开始,令 cwnd = 1(congestion window),发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 …
注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。
如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。
2.快重传与快恢复
在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。
在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。
在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。
慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。
参考
1.github@CyC2018
2.计算机网络(第七版)-谢希仁