深刻浅出图解【计算机网络】 之 【TCP可靠传输的实现: 三次握手+滑动窗口】

【前言】这个系列主要会介绍一些计算机网络体系中“看上去稍有些复杂”但“一旦理解了又会很容易”的内容,我会尝试经过示意图/动图的方式对概念进行尽可能直观的诠释,若是可以对你们学习计算机网络有所启发的话就最好了。缓存

TCP(Transmission Control Protocol)是整个TCP/IP协议族中为数很少的能扛起“可靠传输”大旗的“扛把子”了(上有应用层协议嗷嗷待哺,下有IP协议寄予厚望(注:IP协议是不提供可靠传输服务的))可以肩负如此重任说明它的协议组成必定不简单,不过,做为一个“协议”,它必定也不会很难理解的。服务器

这部分的内容我打算分为两个部分讲解,本篇文章主要会讲解TCP链接的创建和释放(三次握手+四次握手),以及发送端的滑动窗口通常原理;至于一样很重要的“拥塞控制”等内容,我会放到下一篇文章中。网络

提及TCP,咱们应该了解它最突出的特色是“基于链接的传输”和“以字节为单位(面向字节流)”,这两点特色与同是运输层的UDP协议造成了鲜明对比。(UDP不创建链接,以报文为单位,二者的区别有机会会仔细说说)而实现这两点也是TCP可以提供可靠传输的关键。tcp

预备知识

TCP报文结构

TCP_packet

下面简单解释一下报文中一些重要的部分:学习

  • 源端口和目的端口:各占两个字节(16位),端口(Port)是运输层与应用层的服务接口,以实现复用和分用。
  • 序号(sequence number):占4个字节,指本报文段所发送的数据的第一个字节的序号。
  • 确认号(acknowledgement number):一样占4个字节,是指望收到对方下一个报文段的第一个字节的序号。(即收到对方的报文段最后一个字节的序号加一)
  • (部分)标志位(Flags)
    • 确认(ACK):ACK=1时确认号字段(acknowledgement number)才有效;
    • 同步(SYN):SYN=1表示这是一个“链接请求(SYN)”或“链接接受(SYN-ACK)”报文;
    • 终止(FIN):用于释放链接,FIN=1代表报文段发送完毕,要求释放链接。
  • 窗口:占2字节,是用来让对方设置发送窗口的依据。

面向流的TCP协议

再了解了TCP报文结构以后,咱们须要知道,这里的“报文”与咱们常见的“报文”有些不一样。测试

TCP 不关心应用进程一次把多长的报文发送到 TCP 缓存。这和UDP的“给多少装多少”正相反。
TCP 对连续的字节流进行分段,造成 TCP 报文段。
面向字节流计算机网络

那么分段的依据是什么呢?
TCP在创建链接的基础上,发送方能够根据对方给出的窗口值(接下来要提到的:使用滑动窗口实现流量控制)和当前网络拥塞(下一篇文章将要提到的:拥塞控制机制)的程度来决定一个报文段应包含多少个字节(UDP 发送的报文长度是应用进程给出的)。blog

TCP链接的创建(“三次握手”)与释放(“四次握手”)

TCP 创建链接的过程叫作“握手”(handshake),能够说是一个颇经典的不那么贴切但为你们所广泛接受的拟人化称呼。接口

在链接的创建阶段,须要在客户和服务器之间交换三个 TCP 报文段。称之为三报文握手(there-way handshake)
3_way_handshake进程

三报文握手的过程就如上动图所示,是否是其实很简单。
就像是两个隔着很远的人在测试一个电话线路:
“能听见我说话吗?”
“听见了!能听见我说话吗?”
“听见了!”

与创建链接思路类似的,还有“四报文握手”(four-way handshake)的链接释放
4_way_handshake

与创建链接不一样的是,若是某一方想要释放链接,另外一方“不必定”就想跟着释放链接,由于它可能还有东西没传完呢。
就像是俩人打电话唠了好久,其中有我的想要睡了:
“喂,我困了,咱明天再聊吧”
“哦哦,那我最后说几句”
... ...
“好,我说完了,晚安咯”
“晚安”

使用滑动窗口实现可靠传输+流量控制

滑动窗口,实际上就是发送方能连续发出的数据(字节流)的阈值。

如今假设,A收到了B发来的确认号为32(代表B指望收到的下一个报文段的开头序号为32),窗口为20字节的确认报文段,那么A即可以根据这两个数据构建出以下发送窗口:
发送窗口1

A发送11个字节的数据后,发送窗口位置不变,可用窗口变小:
发送窗口2

此时,B收到了前三个字节,向A发送确认号为35的确认报文字段(同时接收窗口向前移动三个字节);
A的发送窗口在收到B的确认报文后也向前移动三个字节。
发送窗口3

这里,就须要引入“中止等待”和“累计确认”的概念了:
中止等待”,顾名思义,就是每发送完一个分组就中止发送,等待对方的确认。在收到确认后再发送下一个分组。
而在TCP传输过程当中,为了提升效率、节约资源,采用了“累计确认”的方式:即没必要对收到的分组逐个发送确认,而是对按序到达的最后一个分组发送确认,表示到这个分组为止的全部分组都已正确收到了

接着,A继续向B发送报文,可是B一直没有发回确认报文。
A在发送至可用窗口为零时便中止发送。
发送窗口4

【后记】 运输层真的是承上启下的扛把子,这其中细节还有不少,今天挑了这两个是由于对于这部分的内容,“直观上的理解”比“文本上的记忆”更为重要。 TCP的拥塞避免也是个很重要的内容,会出如今下一篇文章中。 最后,大家的反馈就是我最大的动力啦(逃