流
大神在一篇文章里描述了流、可靠性、滑窗,我还是分开记吧
问题:"流"通信的意义与实现方式
"流"通信
TCP
协议和UDP
一样,属于传输层协议,所以实现了端口到端口的通信。TCP
协议特别的是,它虚拟了文本流(byte stream
)的通信。计算机数据的本质是有序的0/1序列。如果以byte
为单位,数据序列就叫做文本流。计算机的功能就是储存和处理文本流。CPU + memory + 存储设备
实现了文本流在同一台计算机内部的加工处理。通过一些IO
,比如屏幕和键盘,文本流实现了人机交互。而进一步,如果网络通信能实现计算机之间的文本流交互,那么我们就和整个计算机系统的数据处理方式实现了对接。
目前已经学到的,连接层传输单位是帧(Frame
),网络层传输单位是包(Packet
),而在传输层最为著名的协议就是TCP
、UDP
,虽然它们在同一层,但是它们传输单位并不一样,因为UDP
和IP
它们用的都是数据包(Packet
)的方式发送的,而TCP
则不同,它是使用"流"的形式传输数据的
为啥要用流传输? 比如我们有一个大文件要从本地主机发送到远程主机,使用TCP按照"流"传输的话,我们可以一边接收,一边将文本流存入文件系统。这样,等到"流"接收完了,硬盘写入操作也已经完成。如果采取UDP的传输方式,我们需要等到所有的数据到达后,进行排序,才能组装成大的文件。这种情况下,我们不得不使用大量的计算机资源来存储已经到达的数据,直到所有数据都达到了,才能开始处理。
次序
从例子中可以看到"流"式传输的有一个很重要的特点,是次序(order
)。想要有效率的实现这一点可不简单。TCP
协议是基于IP
协议的,所以最终数据传送还是以IP
数据包为单位进行的。如果一个文本流很长的话,我们不可能将整个文本流放入到一个IP
数据包中,那样有可能会超过MTU
。所以,TCP
协议封装到IP
包的不是整个文本流,而是TCP
协议所规定的片段(segment
)。与之前的一个IP
或者UDP
数据包类似,一个TCP
片段同样分为头部(header
)和数据(payload
)两部分 。所谓的"片段",是指将整个文本流按照次序被分成小段,而每一段被放入TCP
片段的数据部分。一个TCP
片段封装成的IP
包不能超过整个IP
接力路径上的MTU
,从而避免令人痛苦的碎片化(fragmentation
)。
给文本流分段是在发送主机完成的,而碎片化是在网络中的路由器完成的。路由器要处理许多路的通信,所以相当繁忙。文本流提前在发送主机分好段,可以避免在路由器上执行碎片化,可大大减小网络负担。
TCP片段的头部会存有该片段的序号(sequence number
)。这样,接收的计算机就可以知道接收到的片段在原文本流中的顺序了,也可以知道自己下一步需要接收哪个片段以形成流。比如已经接收到了片段1,片段2,片段3,那么接收主机就开始期待片段4。如果接收到不符合顺序的数据包,比如片段8,接收方的TCP
模块可以拒绝接收,从而保证呈现给接收主机的信息是符合次序的"流"。