网络之TCP/UDP漫游

可靠传输的TCP

TCP的可靠传输靠什么保证的,TCP可靠传输面临什么问题,TCP的连接和断开。
TCP和UDP都是应用层之下的协议,都是用来提供端到端的传输服务。那么TCP
和UDP有什么不同。以上都是对TCP协议的一些问题,下面慢慢展开来说。

TCP是面向连接的

TCP是面向连接的,这个问题看到过很多次,每次都有过思考,连接代表什么,
是虚拟电路?这样理解的话,那UDP也在通信过程中建立了一个虚拟电路啊。
很明显,这样的解释并不合理。
那么该如何理解这个连接的意思呢。追本溯源,先看看一下TCP和UDP是怎么
定义的。
UDP:
(1)udp是无连接的,发送数据之前不需要建立连接
(2)udp使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持
复杂的连接状态表
(3)udp是面向报文的,对应用层交下来的报文,添加首部就交付IP层。
TCP:
(1)tcp是面向连接的
(2)tcp连接是1对1的
(3)tcp提供可靠交付的服务,通过TCP连接传送的数据,无差错,不丢失
不重复,并且按序到达。
这里仔细思考一下,tcp可以让传输的数据有序,无差错,不丢失。如果直接
传输,可以保证达到这样效果吗?肯定不可以啊,这里双方都应该保存通信的
状态,哪些数据已经传输了,哪些数据丢失了,哪些数据还没有传输过来,这
都需要双方记录下来(为什么双方,因为tcp是全双工通信,可以作为接受端,
也可以作为发送端),如果数据已经传输了,发送方可以把数据从缓存中清除,
如果数据丢失了,数据丢失了,接收方要通知发送方重传。这些状态都是需要
保存的,对状态的保存就是TCP连接的含义。同样,UDP不需要保存这些状态
所以,UDP是无连接。(当下理解,有错再改)

TCP怎么建立连接

那么根据上面的说法,其实建立连接就是对状态的初始化。生出序列号,同样
也有了确认号,并且数据包的大小,发送窗口的大小都在这是做一个初始化。
那么TCP怎么建立连接呢?
TCP建立连接一般经过三次握手,SYN标志位表示申请建立连接,FIN标志位
表示结束连接。
(1)客户端首先发送带有SYN的数据包给服务器端,并且给出自己的序列号。
(2)服务端收到客户端的数据包后,应该给出一个回应,包含确认号。表示
自己已经收到了客户端的连接请求,同时连接应该是双方都需要确认的,服务
端也发送一个带有SYN的数据包,给出自己的序列号,并且和回应放到一个数
据包中,如果能收到客户端的回应,说明双方的通信没有问题。
(3)客户端收到了服务端的回应,就知道了,服务端能够接收自己的数据包,
并且服务端能够正常发送数据包。这时,客户端给出回应。服务端收到后,表
示自己和客户端的通信可以正常进行,连接建立。之后可以正常通信。
network-1

为什么是三次握手

因为三次握手已经可以确定双方能够正常通信,这也是能够确认双方能够正常
通信的最小次数。
比如,两个人电话交流。
A:喂,听得到吗?
B:我能听到,你能听到吗?
A:我也能听到。
三次交流才能说明双方的语音的发送和接收都没问题,如果是四次就多了,没
有必要,如果是两次呢?B不确定自己的通话对方能够听到。

为什么不是两次握手

网络环境是复杂的,如果发送端第一次发送的连接请求遇到网络拥塞,超过了
重传时间还没收到回应。发送端会重新发送一个连接请求来建立连接,这个连
接走了一个比较畅通的道路,很快就建立建立,并且完成来通信。但是第一个
连接并没有丢失,而是延时到达了,当它到达的时候,又会建立一次连接,但
是这次连接其实已经过时了,只会平白浪费资源。
如果是三次握手,即使第一个连接延时到达,当它请求连接的时候,因为客户
端已经知道连接已经建立了,会拒绝这次连接。

TCP怎么传输数据

经过上面的一系列步骤,连接终于建立完成了。
在阐述TCP怎么传输数据之前,先来熟悉几个标志位,这几个标志位对于理解
TCP是如何传输数据至关重要。
(1)Seq:序号,用于表示本次发送报文段的第一个字节的序号。
(2)Ack:确认号,用于表示期望下一次接受报文段的第一个字节的序号。
(3)len:本次报文段的长度,seq+len=Ack
为了确保每个数据都能被接受到,就需要对每次的传输进行确认。每发送
一个数据报就进行一次确认。
network-2

出现丢包怎么办|停止等待协议

上面的设想是好的,但是网络环境并不是这样的,数据会出现延时或者丢包
如果出现丢包问题该怎么办?
最简单的方法就是发送方确定上一次数据包被接收方收到后,才进行下一次
发送。首先,发送方在发送完数据后给自己一个定时器,如果超过定时时间
还没有收到确认,就重新发送一次。
没有收到确认的情况有两种,一种是自己的数据丢失或者延迟,二是因为确
任丢失或者延迟。
(1)对于发送发放方数据丢失,接收方重新接受发送方重传的数据
(2)对于数据延迟,接收方应该丢弃重复的数据,但是还是要发送确认
(3)对于确认丢失,发送方重传,接收方丢失重复数据,但是要发送确认
(4)对于确认延迟,发送方丢失重复确认就可以了
停止等待
network-3
确认丢失
network-4
确认延迟
network-5

每次只确认一个,效率太低怎么办|滑动窗口协议(ARQ)

每次只发送一个数据包,然后傻傻地等着确认,百无聊赖。珍贵的时间就这样
被消磨了,如果能在等待的时候接着发送数据,想必是极好的。
其实滑动窗口协议就是这样的一个设计初衷,它开始规定一个了窗口大小,可以
连续发送数据包,只要不超过窗口大小就可以。另外,再收到接收方的确认后。
窗口还可以进行滑动。
network-6

滑动窗口协议下的确认机制

现在,有了滑动窗口协议,一次可以发送多个数据包,但是接收方的确认机制
是怎么样的呢?是每发一次进行一次确认,还是会累计到一次的次数后进行确
认?
滑动窗口协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组
的位置,但是接收方一般都是采用累计确认的方式,也就是说,不用对每一个
分组都发送一个确认,可以在几个分组接受后,对按序到达的最后一个分组进
性确认即可。累计确认优缺点都很明显,不用每一次都发送一个确认,这很
明显节省了带宽。但是如果出现丢包,那么在这个包后面发送的数据要重新
发送一次。

选择确认SACK

上面所说的确认机制在丢包的时候可能要重传已经发送过的数据,那么能不
不能只重传丢包的数据呢?TCP给出了一个解决方案,就是选择确认,接受
方将接收到的数据边界发给发送方,发送方能够推算出丢的包。但是由于TCP
首部的option只有40个字节,每个边界都需要4个字节(32bit),所有
总共可以报告4个已经接受到分组的边界。另外8个字节还需要对SACK做说明。
但是SACK文档并没有说明接收方如果设置SACK,所以一般的选择还是重传
丢包之后所有的数据包。

超时重传的时间确定

超时重传的概念很简单,但是如何确定超时重传的时间呢?计算机网络是分组
交换的,有可能会选择较拥挤的路线,也有可能选择较通畅的路线。如果把重
传时间设置过小,可能会造成不必要的重传。如果超时重传的时间设置的过大,
又可能使网络空闲的时间过大,降低了传输效率。
TCP采用的是一种自适应的算法,它记录一个报文段发出的时间,以及收到相应
确认的时间。这两个时间差就是报文段的往返时间RTT。TCP保留了RTT的一个
加权平均往返时间RTTs.
new RTTs = (1-a)×(old RTTs) + a×(new RTT)
first RTTs = first RTT
a的推荐值为0.125
RTTd是RTT的加权平均值
new RTTd = (1-b)× (old RTTd)+ b × abs(RTTs - new RTT)
first RTTd = half of fisrt RTT
b的推荐值是0.25
RTO = RTTs + 4 × RTTd

TCP流量控制和拥塞控制

TCP如何在复杂的网络环境中进行资源的最大利用,并且又不会增加网络的负担,
如果根据网络环境来选择自己的发送窗口的大小。

发送窗口大小的制约因素

发送窗口肯定不是无限大的,有两个因素在制约着它,一个是接收方的接受
窗口,如果接收方的数据还在处理,没有多余的空间来存放发送的分组,那么
发送的数据就会被丢弃。所以发送窗口的大小要有接收方的接收窗口制约,不
能大于接收方的窗口大小。另外一个就是网络因素,如果网络出现拥塞,应该
适当的减小发送方的窗口,不然只会使得网络环境更加拥塞。
size(发送窗口) < min(size(拥塞窗口,size(接收窗口))

慢启动和拥塞避免

在TCP刚连接开始,本机是不知道网络环境是怎么样的,不知道当前网络环境
是拥塞还是畅通。所以本机只能谨慎向网络中发送数据,先将拥塞窗口设置为
2(RFC推荐MUST be less than or equal to 2*SMSS bytes and
MUST NOT be more than 2 segments.),然后发送2个数据包后会收到
2个确认,把拥塞窗口设置为2+2;然后下一次可以连续发送4个数据包,以此
类推,当拥塞窗口到达慢启动阈值的时候或者侦测到拥塞时,慢启动就结束了。

慢启动阈值

初始的慢启动阈值可以是任意值,启动慢启动算法,当侦测到网络拥塞时,就
可以将慢启动阈值设置为发生拥塞时发送窗口的1/2.之后,只要发生拥塞,就
用上面的方式设置慢启动阈值。

拥塞侦测

在TCP连接中,只要发送的数据超时没有收到确认,就认为网络发生了拥塞。

如果拥塞窗口到达了慢启动阈值,那么接下来就使用拥塞避免算法,在每个
RTT收到确认后会让拥塞窗口增加一个MSS,直到发生拥塞,拥塞窗口重新设置
为一个比较小的值,继续慢启动算法。
network-7

快重传与快恢复

快重传是在接收方意识到对方丢包,自己收到了一个乱序的数据包,自己主动
发送多次相同的确认,让发送方尽早知道自己丢包了,然后把丢失的数据包发送
过来,而不是等到重传计时器时间到了再重传。一般是接收方收到乱序的数据
后连续发送三个确认给发送方,发送方连续收到三个重复确认就需要重传丢失
的包。
但是既然能够连续收到三个重复确认,说明网络环境并没有那么糟糕,不然应
该会出现丢包问题,不可能收到三个重复确认。这时候使用慢启动就显得不是
那么合理,所有利用快恢复来解决这个问题。
当方法方连续收到三个重复确认,就把慢启动阈值设置原来阈值的1/2,并且这
拥塞窗口并不是直接设置为1或者2这么小的值,而是也设置为原阈值的1/2,
并且之后使用拥塞避免算法。
在采用快恢复算法的时候,只有在TCP连接建立时和网络出现超时重传时才使
用慢启动算法。
network-8

TCP怎么终止连接

TCP终止连接称为四次挥手。
(1)想要结束连接的一方发送带有FIN的数据包
(2)另一方接收到FIN数据包后就发送一个确认。
(3)另一个此时也发送一个FIN数据包
(4)该机接收到FIN数据包后,给出一个确认,这时候连接完全断开。
关于TCP连接和终止连接的问题还有更深入的细节需要讨论,会在其他文章中讨论。

本文标题:网络之TCP/UDP漫游

文章作者:learner66

发布时间:2018年07月11日 - 14:32:14

最后更新:2018年07月12日 - 15:45:20

原始链接:https://learner66.github.io/2018/07/11/network-tcp-udp/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

------ 本文结束,感谢您的阅读------