高门槛,勿入

Cisco平台上有一个很有用的Traceback

log功能,实时记录当前Code运行到特定模块、特定函数,这样一旦系统崩溃、死机的时候,可以有效记录机器是在哪个模块、哪个函数里崩溃的。只要将此Traceback输入解析器,就可以定位是哪个模块出了问题,提交Bug的时候就可以Assign给负责此模块的Team,避免部门之间的推诿。

其实Traceback的原理也很简单,即每进入一个模块,就记录一下实时位置,类似于Debug。TCP/IP协议如果也拥有类似的traceback日志信息,那么只要用packet触发一下,就可以实时看一个packet如何在TCP/IP内部函数流转,在packet被递交给网卡之前,打印出每一个函数的名称,然后进入TCP/IP源码,按照函数调用的先后次序(流水线)依次进入阅读,只有这样才能详细了解TCP/IP细节。

但是这样的学习门槛很高,源码也不是那么可以轻易看懂。对于大多数读者来说,更容易的方法是先易后难,在开始TCP/IP学习之前,先问自己一个问题,为什么要有TCP/IP协议?

计算机网络的标准件

TCP/IP是计算机网络世界的标准件,这些标准件类似于汽车界的标准轮胎、汽车稳定系统ESP,即使看似牛叉的Tesla汽车生产商,也不是所有汽车零部件都是自己生产。除了电池、外壳、软件是自己生产的除外,其他的标准件全部是采购而来。通过使用标准件,平均只要几分钟即可生产一辆汽车。如果不使用标准件而全部采用自研,那生产的周期要大大加长。

既然TCP/IP是标准件,是不是也要像汽车轮胎一样提供标准的接口?否则怎么安装呢?

是的,TCP/IP提供了诸多的标准接口,通过这些标准接口可以有效使用标准件,如DNS、TCP、UDP、IP、ICMP、IGMP、ARP、DHCP等等标准件。当然如果一一介绍这些标准件如何使用,这些标准件内部的工作原理是非常枯燥的,还是以小例子看看这些标准件是如何协作的。

一个小例子

在浏览里输入知乎的网址(zhihu.com),然后输入回车,浏览器使用的TCP/IP第一个标准件是什么呢?

读者说,浏览器与知乎服务器通信使用http,而http通常是使用标准件TCP的,那么第一个标准件应该是TCP,对吗?

不对。

TCP这个标准件,对于http来说身份是服务员,尽管TCP身份低微,但是却有鲜明个性。就是任何人差遣自己干活,必须使用IP地址。浏览器不能使用网址(zhihu.com)这个字符串来差遣自己,罢工。

标准件之DNS

所以,浏览器使用第一个TCP/IP标准件是DNS。DNS其实就是将知乎的网址(zhihu.com)解析成一个IP地址。有了知乎的IP地址,才能使用TCP这个标准件。

读者会说,DNS域名查询,会使用UDP这个标准件,UDP标准件会使用IP标准件,IP标准件直接会使用以太网卡标准件,对吗?

不对。

以太网卡标准件,作为IP标准件的服务员,尽管身份卑微,但是个性鲜明,凡是让自己干活的客人,必须提供接收方的MAC地址,否则恕不接待。

所以IP标准件需要先使用ARP标准件,查询接收方的MAC地址。

读者又说,ARP这个标准件使用的也是以太网卡标准件,没有接收方的MAC地址,以太网卡不是恕不接待的嘛?

是的。

但是ARP使用广播MAC地址(FFFFFFFFFFFF)来查询啊,所以以太网卡不得不执行查询任务啊。

假设一切顺利,ARP得到了回复答案,将ARP答案返回IP标准件。

既然IP标准件拥有了接收方的MAC地址,就可以使用以太网卡标准件,将packet提交给以太网卡,packet的进一步处理就和TCP/IP没有关系了。

不一会DNS查询结果报文返回,按照时间先后次序进入网卡物理层、MAC层、IP标准件、UDP标准件、DNS标准件,由DNS标准件将查询结果告知浏览器。

以上的DNS查询过程,浏览器其实只直接使用了DNS标准件,并没有直接使用其它标准件,其他标准件的使用都是由DNS标准件(进程)间接触发使用。

有读者会说,DNS标准件、ARP标准件功能非常清晰也很有必要,多出来的那两个标准件IP、UDP看起来非常多余,为什么要有它们啊?

标准件之IP

问读者一个问题,浏览器查询得到知乎的IP地址,是留给自己看的吗?

很显然不是,IP地址肯定是给互联网看的,准确地说是给互联网上的IP路由器看的,IP路由器看了知乎的IP地址,才能将IP报文快递到知乎服务器,不是吗?

知乎的IP地址写在什么地方呢?

写在packet的IP报文头。

由谁来写

IP标准件,IP标准件所做的工作远不是在包裹的外层添加一个IP封装,并在外包装上写下知乎的IP地址(目的IP)、浏览器主机的IP地址(源IP)那么简单,还需要查询路由表,寻找合适的出口。否则一个主机有多个网卡,连接内网和互联网,主机怎么将访问知乎的packet发给连接互联网的网卡,而不是连接内网的网卡呢?这就是IP标准件的另外一项主要工作。而要完成种种复杂的工作,最好的方式就是以一个实例instance形式(进程)存

标准件之TCP

再返回第一个问题,浏览器拥有了知乎的IP地址,是否就可以将http request用TCP标准件发出了呢?

依然不行。

TCP这个怪癖狂,非常有个性,要想使用它必须遵守它的怪癖。这个怪癖是什么呢?

Create()

需要先要调用TCP标准件一个Create指定,该指令其实就是在本地内存创建一个结构体(内存),用于缓存TCP连接所有相关的变量、数据,最最重要的是这个结构体有一个全局唯一的ID,浏览器以后要与TCP标准件沟通,只能使用这个唯一的ID(FD)。

Okay,TCP结构体创建成功,是不是就可以发送http request了?

依然不行。

Connect()

TCP需要先建立连接,因为上文的结构体是空白的,需要建立连接将关键参数进行初始化,双方的ISN,MSS、Window Size、SACK、Scaling Window等等。

建立TCP连接,使用TCP标准件的connect接口,填入合适的参数,最重要的是知乎IP地址以及知乎端口,是80还是443,这将决定接下来是否需要使用TLS标准件,前者不需要,后者需要。

这就是大名鼎鼎的TCP三次握手,其实三次握手一点也不准确。真实的含义是三个packet完成连接,浏览器发2个packet,知乎服务器发1个packet。之所以一直就这样以讹传讹到现在也没有纠正,是因为英中翻译这样最顺口。

需要指出的是,TCP尽管有很多怪癖,但是connect环节以及之后的环节还是非常友好的。你只要调用一次connect即可,至于浏览器是发2个packet连接成功,还是多次重传连接成功,这都是connect接口内部的实现,浏览器无需关心。Connect只会告知浏览器两个结果,成功或者失败。

读者有点急不可耐了,TCP连接建立成功,http request是否就可以发送出去了?

Send()

如果浏览器连接的是知乎TCP 端口80,是的,浏览器需要将http

request数据通过调用TCP标准件send()接口发送出去,浏览器调用接口时需要携带FD唯一ID。

如果浏览器连接的是知乎TCP 端口443,即https服务,依然不能发送数据。浏览器需要使用TLS标准件,与知乎服务器完成TLS安全加密连接才能发送http request。

标准件之TLS

尽管TLS是一个标准件,但是它却工作于TCP之上,即TLS依赖于TCP为自己提供服务。所以TLS不是传统意义上的TCP/IP标准件。

TLS安全连接,使用上文创建的唯一文件标识符FD,使用TCP标准件的Send()、Receive()完成双向数据的收发,当浏览器认证知乎服务器数字证书合法双方协商出加密/解密参数,至此TLS标准件通知安全连接创建成功或者失败。

浏览器的http request终于可以发出了,先流经TLS标准件,添加TLS 报文头,数据加密+数据完整性保护。再流转到TCP标准件,添加TCP报文头并发出,等待对方确认,启动超时重传定时器。再流转到IP标准件,查路由找出口,添加IP报文头。最后到达网卡,使用IP标准件提供的参数,完成以太网封装,进入发送队列。一旦轮到该报文,由物理层添加Preamble

+ SFD + CRC将信号发送出去。

上文标准件调用的过程中,最值得研究的就是TCP,只有它对来自浏览器的http request进行了数据缓存,并启动了定时器。假设第一次发出的http request在互联网被丢了,对该http request重传的,既不是浏览器、也不是TLS、也不是IP、更不是以太网卡,而是那个有诸多怪癖的TCP,通过多次重传以应对可能丢包对浏览器数据的影响,这也是TCP可靠性的真正含义。浏览器一梭子打出去之后就不管数据死活了,TCP接管数据的重传重任。

标准件之UDP

最后说到UDP,看了上文的TCP发数据的过程,是不是觉得很繁琐?是的,不光繁琐而且非常耗时,如果连DNS查询也要使用TCP传输,意味着用户需要等待更长的时间才能开始传输真正的数据,需要用户有更长久的延迟满足,很显然耐心不够的用户会直接放弃。

而有了UDP就没有那么繁琐了,用户使用UDP发送数据数据,无需等待、无需建立连接,直接嗖得一声,数据就UDP、IP、以太网走起,紧凑整洁,节省了用户大量时间。

比如基于IP的实时语音以及视频,为了良好的用户体验,通常需要50ms收发一个包裹,要到达这个低延迟,使用TCP很显然是无法完成的,剩下的唯一选择就是使用UDP来承载。

TCP/IP做为计算机网络标准件的集中营,每一个标准件都可以直接调用,而不全是上文的间接调用。比如用户可以直接使用IP标准件、ICMP标准件写程序,甚至直接调用以太网卡标准件,而不仅仅局限于TCP、UDP、DNS、TLS。