黄东旭解析 TiDB 的核心优势
845
2023-06-30
本文讲了TCP如何实现可靠的数据传输服务,可靠数据传输服务。
总观TCP
TCP为成对的应用提供通信服务。它允许一台主机上的某一个应用与另一台主机上的某一个应用进行通信,允许同一台主机上的多个应用同时进行可靠稳定,不受干扰的数据通信。TCP使用协议端口号来区分不同的应用。TCP的特点有
点对点,即在一个发送方和对应的接收方之间建立逻辑连接
基于连接的,即需要首先建立连接(三次握手),连接建立后进行数据传输,最后断开连接(四次挥手)
全双工数据,即数据流在同一个通信中是双向的
可靠的连接,即使用Go-Back-N和Selective Repeat的方法(有checksum,重新传输,累积的或有选择的ACK还有计时器来判断有没有超时)
有管道的(有滑动窗口的传输方法)
有流量控制的,即发送方和接收方都具有缓存机制
TCP首部格式
可靠的数据传输服务
TCP保障接收方一定能收到数据,发送方一定会最终被通知,但是TCP的可靠的数据传输服务是建立在IP的不可靠的服务上的,所以这里就需要借助重新传输来实现。
自适应重传
RTT(round-trip time)会根据实际网络的情况不断被重新估计,计时器会不断根据RTT来计时,从而适应不同的TCP通信。
发送方的情况
1. 接收方发回的ACK丢失
发送方在超时后未收到ACK,重新传输
接收方收到重复数据后直接丢弃,再重新发送ACK
2. 超时
发送方在超时后重新传输
发送方收到接收方发来但迟到的ACK,于是进行更新
接收方收到重复的数据,直接丢弃并发送最新的ACK
3. 累积的ACK
就算之前接收方回传的旧的ACK丢了也不要紧,发送方会直接更新最新的ACK。
接收方的情况
收到按顺序到达的segment
如果所有的segment(包括现在的segment)都已经发回ACK了,那么会延迟500ms发送该ACK以等待下一个segment,如果超过500ms仍然没有下一个segment,才会发送该ACK
如果除现在的segment外的其他segments都已经发回ACK了,那么会马上发回当前收到的segment所对应的ACK
收到不按顺序到达的ACK
马上发回之前已经重复发过的ACK,索要中间空缺的segment。直到收到了中间空缺的segment,就会直接发回最后一个(橙色)segment对应的ACK
TCP快重传
由于通过超时重传总是要花相对较多的时间,所以TCP快重传问世。因为接收方收到不按顺序的segment会连续发送相同的ACK,所以TCP快重传通过3个重复的ACK来判定segment是否延时未到或者是丢失。只要收到3个重复的ACK,发送方就不会等到超时再重传,而是会直接发送ACK对应的segment
TCP流量控制
接收方可以通过ACK中的窗口字段控制发送方的窗口大小,从而使得segments不会在接收方的缓存(窗口)中溢出。每一个ACK都明确了接收方缓存中的剩余空间。
下面是一个例子:
假设Maximum Segment Size(MSS)是1000,接收方窗口大小是2500。接收方发回的ACK中包含了接收方窗口剩余空间的值。当该值为0时,发送方就不会发送segment
TCP的连接管理
建立连接:三次握手
假设客户端想要与服务器建立连接
客户端发送SYN segment到服务器,这里会随机选择一个初始序列号(ISN)并赋值给Seq(假设为x),SYNbit=1
服务器收到SYN segment后,随机选择一个初始序列号(ISN)并赋值给Seq(假设为y),SYNbit=1,ACKnum=x+1,ACKbit=1
客户端收到ACK/SYN后,发送连接确认报文段,ACKnum=x+1,ACKbit=1
终止连接:四次挥手
假设客户端打算终止连接
客户端发送连接释放报文,FIN=1,随机选择一个初始序列号(ISN)并赋值给Seq(假设为x),然后进入FIN_WAIT_1,只能收数据不能发数据
服务器收到连接释放报文,发送ACK,ACKbit=1,ACKnum=x+1,然后进入CLOSE_WAIT,还可以继续发数据
客户端收到ACK,进入FIN_WAIT_2
服务器发送连接释放报文,FIN=1,随机选择一个初始序列号(ISN)并赋值给Seq(假设为y),然后进入LAST_ACK,在这里也不能再发数据了
客户端收到连接释放报文,发送ACK,ACKbit=1,ACKnum=y+1,然后进入TIMED_WAIT,在等待2*MSL(Max Segment Lifetime)后进入CLOSED状态
服务器收到ACK后直接进入CLOSED状态
TCP拥塞控制
拥塞控制和流量控制很相似,但流量控制是为了使得接收方来得及接收,segment不会溢出,而拥塞控制是为了降低整个网络的拥塞程度。拥塞控制使用Congestion Window(cwnd)来控制传输的segment,真实的窗口大小=min(rwnd,cwnd)(rwnd是Receiver Window)
TCP发送方可以通过超时和接收到3个重复的ACKs来判断是否出现网络拥塞,3个重复的ACKs可以运用TCP快重传解决。
要想理解可靠数据传输(Reliable Data Transfer),那么不妨结合与其相对的概念——不可靠数据传输进行理解。
UDP可靠性设计、TCP/UDP应用场景分析
什么是可靠数据传输服务?什么是可靠数据传输协议?
比如我们要实现这样的一组通信,发送方通过一个网络协议给接收方发送一些数据分组,接收方有可能接收到了全部数据,也可能因为各种原因只接收到了部分数据分组或者根本没有收到任何数据分组。即使收到了全部的数据分组,但可能这些分组是有序的(或者说可以通过一些操作恢复为发送时的顺序)可以得到完整的消息(message),也有可能是无序的,无法恢复出完整的信息。即使数据包是完整的、有序的,有可能在某些地方因为信道有噪声或者其他缘故出现一些差错,导致数据上出了偏差。
协议要保证的不仅仅是发送方可以发数据,同时也会对接收方将接收到怎样的数据做出一定的保证,这才是完整的通信。
Thus, to support these applications, something has to be done to guarantee that the data sent by one end of the application is delivered correctly and completely to the other end of the application. If a protocol provides such a guaranteed data delivery service, it is said to provide reliable data transfer.
分组可能会在网络中丢失、损坏,应用层可能对网络通信有所要求,不允许出现这种差错,必须保证接收方的应用收到了完整且正确的数据,这种服务就是可靠数据传输服务。
如果一个协议可以确保发送端发送了怎样的数据,那么接收端就必然能接收到怎样的数据,那么就可以说这个协议提供了可靠数据传输服务,这个协议是可靠的,反之则是不可靠的。
类比一个比较形象的场景,一个记者去现场报道国家主席接见现任特首,那么这个记者就相当于一个通信协议,如果能保证把所有的信息都完整、真实、无差错地报道出来,让观众、读者可以通过她的报道真实感受现场情景,那么她就提供了可靠的数据传输服务,如果她可能故意问一些没有质量且水平低下的引导性问题,丢失一些信息没有完全报道,夹带私货,把无中生有的事再重复一遍,宣传上就出现了偏差,她就是不可靠的记者(协议)。
2.为什么形容一个协议是可靠/不可靠的?为什么说TCP是可靠的,UDP是不可靠的,IP也是不可靠的?
TCP服务模型除了面向连接以外,也提供可靠数据传输服务。
The communicating processes can rely on TCP to deliver all data sent without error and in the proper order. When one side of the application passes a stream of bytes into a socket, it can count on TCP to deliver the same stream of bytes to the receiving socket, with no missing or duplicate bytes.
通过TCP协议的通信进程可以无差错地以正确的顺序传送所有数据。当一方的应用向套接字传送字节流时,它可以通过TCP向接收套接字传送完全相同的字节流而没有丢失或者冗余的字节。
而同样是传输层的重要协议UDP则不提供可靠传输服务,仅仅提供最小服务(minimal services),是无连接的。与之相对,无法保证接收套接字接收到的字节流是完整的、无差错的、有序的。
传输层之下的网络层,主要使用的是因特网协议(IP协议)。IP协议是一个尽力而为(best-effort)的传送协议,只实现通信方之间逻辑上的连接,IP协议只能尽力去传送通信双方的报文段,而不作出任何保证(完整性、正确性、有序性)
2.1 为什么可以同时允许可靠/不可靠数据传输服务的存在?
在实际上的通信实现中,选取怎样的协议,设计怎样的协议栈,协议本身特性固然重要,但也有考虑通信需求的进程。说具体一些的例子,一般常用的应用涉及的也就是TCP和UDP的选择,当然现实中还是使用TCP较多,因为大多数应用对数据的完整性、正确性有很高的要求,比如邮件服务/文件下载,但是对吞吐量和时间却没什么要求,而有些应用比如视频游戏/即时通讯对实时性的要求非常高,对数据丢失却是可以容忍的,视频聊天的时候清晰度不高或者出现小规模马赛克,略显失真不是什么大事,所以这个时候选用UDP协议更合适。
还是沿用上面的类比,传输层协议就像记者一样,每个记者的技能点不一样,一般情况下我们当然会偏爱知识水平高、立场客观真实的西方记者,所以他的出勤会比较多比较著名。那么香港记者经验不足太肤浅、年轻不足以报道全部内容,她就一无是处吗?不是的,她就像UDP,不存在任何拥塞控制而且轻量简单(simple),跑的比谁都快,善于弄大新闻,对于实时性很高的新闻事件让她去也很合适。
因此应用层上的每个协议都会根据需求选择与之对应的传输层协议。
3.怎样实现可靠数据传输?
对于底层信道完全可靠的情况,只需要调用跟着基本法来,接到上层调用就做一系列操作(打包之类的)把数据发给下层,接收方对应层协议收到下层的调用就将数据做些操作然后发给上层协议,其他的就不需要考虑了。
我们已经在2.1提到,IP是不可靠的,但是可以依靠上层的协议(如TCP)使这个使用IP协议的通信变得可靠,这就好比记者在采访现场引导出了一些不符合积极向上的个人形象的言辞,但是没关系,上层还有编辑和其他审核人员,他们的专业技能可以保证把通讯稿写的符合基本法,那么宣传上就不会出现偏差。
现在要解决的问题就是怎样在不可靠的网络层协议之上实现可靠的传输层协议。这里以在IP上实现的TCP为例。
3.1 差错检测
包括奇偶校验、校验和、CRC等方法判断收到的数据分组是否损坏,如果不能校正那就丢弃分组。
3.2ACK确认
这是在不可靠底层信道上加入的一种反馈机制,由接收方发送确认消息。发送方发送数据,接收方接收到了以后发了ACK表示“我已经收到了,可以继续发了”,就像发了一个“支持XXXX吗?”对方回答“吼啊”你才可以继续提问,如果你问的那么热情对方一句话也不说,这就不好了,虽然不排除无可奉告的可能,但是也不能再继续问下去了,这个模式就是停止等待(stop-and-wait)协议的思想,只有得到肯定的确认才能继续发送数据。除了肯定确认ACK表示确认收到以外,还有否定确认NAK,用来表示某个数据没有收到,比如滑动窗口协议中用的就是NAK,意思就是“没听说过”。
发送方收到了接收方发来的ACK/NAK后自己也要判断的,然后再把接收方丢失的数据分组(无论是在信道上丢失的还是因为出了偏差所以主动丢弃的)重传一遍。
以上其实就差不多是停止等待协议的基本内容了。
3.3 序号
但是ACK/NAK也可能在传输过程中被损坏,这时候就需要引入序号(sequence number),接收方可以通过检查收到的数据分组的序号发现哪些分组没有收到、哪些分组冗余了。发送ACK/NAK反馈时也可以指定Seq表示需要重传哪些分组或者继续往下发送哪些分组。序号的引入也让传送的效率大大提升,不用像停止等待那种朴素(naive)方法受限于当前的分组战战兢兢,可以以流水线传送数据。
4.后记
“如何理解可靠数据传输”这个问题实在太大,仅仅从概念上来讲就已经非常大了,我不知道题主需要的是具体哪方面的内容,所以把最基础的部分写出来了,事实上比如重传中的超时机制也是很重要的,虽然涉及了一些最基础的元素,但是基础的方法比如退回N步(Go-back-N)、选择重传(SR)、滑动窗口之类也都很重要,但是我的篇幅和精力有限,无法兼顾,只能带你进门,剩下的学习要你自己去完成。这还仅仅是概念,源码阅读和实际应用也需要你自己多多考虑一下。
References
[1] Velten, David, R. M. Hinden, and Jack Sax. Reliable data protocol. No. RFC 908. 1984.
[2] Kurose, James F. Computer Networking: A Top-Down Approach Featuring the Internet, 3/E. Pearson Education India, 2005.
上文就是小编为大家整理的TCP如何实现可靠的数据传输服务,可靠数据传输服务。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。