前端进阶必须懂得TCP/IP

TCP/IP四层协议

一往无前虎山行,拨开云雾见光明。梦里花落牡丹亭,幻想成真歌舞升平。 —— Gai

计算机网络的结构分层

  • 物理层,相当于是那些物流公司里的送货汽车
  • 数据链路层,可以看作是物流公司的司机,他们驾驶着汽车,将打包好的货物(数据帧)从一个城市(物理节点)运输到另一个城市。
  • 网络层,这好比是物流公司的路线规划者。物流公司有很多集散中心,根据集散中心的情况(是否拥堵),找出一条经过n个集散中心的路径将货物(数据)沿路运过去。
  • 传输层,可以将其看作是物流公司的跟单员。负责任的跟单员(使用 TCP 协议)会保证数据送到客户手上,如果送不到(需要三次握手,四次挥手)就让公司再发一次。不负责任的跟单员(使用 UDP 协议)层只管将快递送到客户指定的地方,不管快递是否送到客户手上。
  • 会话层,可看作是物流公司的调度员。他管理着这次物流的相关的信息。例如这次客户要发很多数据,发到哪,到底是一车一车发、还是用轮船一次运过去。这些都是他的职责。而运完之后,相关信息(连接)也可以被销毁了,这也是调度员的职责。
  • 表示层,相当于物流公司的打包员。如果快递(数据)太臃肿,他会在不破坏快递的情况下压扁(压缩)它。如果客户注重安全线,全能的快递公司还能用密码箱( SSL/TLS)打包快递再快送。当然,打包员会确定,目的地快递站的拆包员,能无损地拆开包裹,将快递交给用户。
  • 应用层,可以想象成物流公司的收件员,当客户(应用)打电话(发起请求)给收件员(应用层)时,收件员可以根据用户的不同需求提供不同的服务(不同协议),比如隔天送达、指定时间送达等等。

TCP/IP协议族

  • TCP/IP从上往下走的时候,会分层的传输进行通讯。
  • 发送端是从应用层链路层,接收端是从链路层往上到应用层取数据。
  • 其中通过各种首部的包装来让相应的层进行识别
  • 这里我拿了网上copy的一张通用的图来看一下。

  • 每层协议需要实现的功能:
    • 将上层协议传递的数据包包装为满足该层协议的数据包
    • 将下层协议传递的数据包解析为满足上层协议的数据包
    • 处理其他层的交互

  • 这和上图要表达的意思差不多,需要注意的是
    • 从底往上传的二进制包,只要该层能处理就不需要按照严格意义上的分层解析
    • 比如说,网络层往上传二进制包的时候,你可以在传输层包一层tcp头,也可以不包,直接交给应用层解析

数据包

帧、数据包、段、消息(传输数据单位)

  • 帧:用于表示数据链路层中包的单位;
  • 数据包: IP 和 UDP 等网络层以上的分层中包的单位;
  • 段:表示 TCP 数据流中的信息;
  • 消息:指应用协议中数据的单位。

数据在每个分层中的体现

  • 每个分层中,都会对所发送的数据附加一个首部
  • 在这个首部中包含了该层必要的信息,如发送的目标地址以及协议相关信息。
  • 通常,为协议提供的信息为包首部,所要发送的内容为数据。在下一层的角度看,从上一层收到的包全部都被认为是本层的数据。

在上面我们就能直观地看到,每一层的数据之外,其实包了很多层协议的首部

数据链路层

探究:数据链路层到底干了什么?

  • 主要是做了接受IP数据报,并发送IP数据报至IP模块
  • 与ARP及RARP模块交互
  • 它的结构可以分为如下
    • 业务区:最底下的那些物理机构成的区域,是物理层流出的起点。
    • 接入层:业务区往上的千兆交换机,这里的物流机如果想互相通信,就必须通过这个交换机。
    • 核心交换机:由一组千兆交换机组成。
    • IDC路由骨干:路由器组成。

Wireshark抓包,看看数据链路层在传输时变成了什么?

  • 首先这个是Wireshark给我们解析出来的TCP/IP协议族的四层。
  • 从上至下,分别是链路网络传输应用
  • 我们着重看链路层,因为链路层在网络层之下,此时的地址都为硬件地址。
  • 只有通过硬件地址,物理层才能将数据包通过路由传至目标地址。
  • 这里就会有一个问题:怎么通过IP地址去获取硬件地址呢?

ARP协议

作用:

  • 将32bit的IP地址,转换为48bit的以太网地址。
  • 发送ARP广播,获得目的端的IP地址和硬件地址。

要注意的问题

  • 访问不存在的主机地址超过时间一般为75s,这个时间其实一般就是TCP连接请求的超时时间。
  • 如果ARP回答未返回,那么任何TCP报文段都不会发送。

如何捕获ARP数据?

  • telnet
  • tcpdump(相当于无界面的Wireshark)
  • 命令:
    • arp -a:查看arp高速缓存。(每个已经找到的mac地址都会在arp中缓存
    • tcpdump -i 网络接口arp:监听网络接口的ARP
    • tcpdump -D:查看可监听的网络接口。

MTU是什么?

最大传输单元。

  • IPMTU就是最大的传输单元
  • 每个路由都会有一个规定的MTU大小
  • 如果我们传送的IP数据包大于这个MTU,就会漏传
  • 需要遵循短板原理,根据最小的MTU来设置IP数据包大小。

总结

  • 主要就是通过发送端的IP地址,在内网(局域网)中通过广播的方式,去询问对应IP的以太网地址
  • 如果访问不到,超过75s,就不会继续广播
  • MTU控制我们传输的大小。
  • 如果我们访问的不是局域网,属于公网,那么我们还通过ARP来寻找mac地址吗?如果是这样,那么我们将会给每个公网发送一个广播,那得有多恐怖,所以ARP只存在局域网
  • 上面这种情况,我们先通过DNS解析得到对应的网络IP地址,再通过找上层的路由去寻找,此时路由发现不是局域网,将会在往上寻找ISP(Internet Service Provider),最后找到对应的mac地址

网络层(IP协议)

上面说到的路由,和它息息相关的就是我们的网络层,最为核心的一层。

协议组成(必须严格遵守顺序)

  • 版本:4位
  • 首部长度:4位,⚠️注意,这里的每1位表示10进制x4个字节的数目。因为4位最大的个数为1111,即15,所以首部最长为15x4,60字节
  • 服务类型:8位,大部分实现不支持,无需关注
  • 总长度:16位,所以最大的IP包为65536
  • 标识:16位,唯一标识主机发送的每一份数据报
  • 3位标志+13位片偏移:暂时不关注
  • 生存时间:8位,数据报最多可经过的路由数(如果不设置这个,就会无限回传)。
  • 上层协议:8位,表明该IP数据报对应的上层协议是什么。
  • 首部校验和:16位,保证IP数据报传输正确。
  • 源IP地址:32位。
  • 目的IP地址:32位。

  • 上面是Wireshark抓的包的IP层,可以清楚看到每个协议的组成。
  • 需要注意⚠️
    • 假如我们发的是公网IP,此时我们无法用ARP找到远端mac地址
    • 需要通过发送给路由,所以我们需要路由的mac地址
    • 本来数据链路层以太网首部放的是本机mac地址和目标mac地址
    • 现在放的是本机mac地址和路由mac地址
    • 而我们的目标IP地址源IP地址则是包在IP首部之中,最后交给路由,让路由处理。

路由选择

  • 每一个IP数据报在网络中进行传输的目的,要找到目的IP的主机地址,并最终到达该主机。所以IP数据报经过的每一个节点都相当于是一个中转站,也就是路由
  • IP数据报被路由节点的操作称为路由选择
    • 动态选路:根据当前网络状况权值,选出一条最佳路径。
    • 静态选路:以手工方式为每台路由器的路由选择表添加路由。
  • 常规的路由机制
    • 目的主机与源主机直接相连,或处于共享网络,直接送达目标主机(相同内网下)。
    • 默认转发至该网络存在的路由器上,再由其统一处理。
  • 路由匹配算法
    • 路由表中存在与目的IP地址完全相同的条目,直接发送至下一跳。
    • 路由表中存在与目的IP地址网络号相同的条目,发送至该条目指定的下一跳。
    • 以上条件均不成立,寻找默认条目,发送至该条目指定的下一跳。
    • 均不成立,返回主机或网路不可达。

  • 假如我们此时的目标IP地址为192.168.0.100,此时会匹配第一条,他的Gateway就是目标的mac地址,en0是网卡,我们可以通过ifconfig查看(windows用ipconfig)
  • 假如我们此时目标IP地址为192.168.0.103,此时路由表没有对应IP地址,则会去寻找相同网络号,此时找到第二条,他的Gatewaylink#8相当于广播出去。
  • 假如我们此时目标IP地址为192.168.1.2,此时无法在路由表中匹配,则走default,对应第三条,他的Gateway对应192.168.0.1192.168.0.1其实就是我们的路由器

上面有提到判断网络号相同,这个我们怎么来做呢?


如何判断两个IP地址网络号相同

IP地址的分类

类别 最大网络数 IP地址范围 最大主机数 私有IP地址范围
A 126(2^7-2) 0.0.0.0-127.255.255.255 16777214 10.0.0.0-10.255.255.255
B 16384(2^14) 128.0.0.0-191.255.255.255 65534 172.16.0.0-172.31.255.255
C 2097152(2^21) 192.0.0.0-223.255.255.255 254 192.168.0.0-192.168.255.255
  • IP 地址分为五个级别,分别为A类、B类、C类、D类、E类。它根据 IP 地址中从第 1 位到第 4 位的比特列对其网络标识和主机标识进行区分。D、E类属特殊地址。
  • A 类 IP 地址是首位以 “0” 开头的地址。从第 1 位到第 8 位是它的网络标识。用十进制表示的话,0.0.0.0~127.0.0.0 是 A 类的网络地址。A 类地址的后 24 位相当于主机标识。因此,一个网段内可容纳的主机地址上限为16,777,214个。
  • B 类 IP 地址是前两位 “10” 的地址,一般是公网。从第 1 位到第 16 位是它的网络标识。用十进制表示的话,128.0.0.0~191.255.0.0 是 B 类的网络地址。B 类地址的后 16 位相当于主机标识。因此,一个网段内可容纳的主机地址上限为65,534个。
  • C 类 IP 地址是前三位为 “110” 的地址。从第 1 位到第 24 位是它的网络标识。用十进制表示的话,192.0.0.0~223.255.255.0 是 C 类的网络地址。C 类地址的后 8 位相当于主机标识。因此,一个网段内可容纳的主机地址上限为254个。

子网掩码

  • 为了细分更小力度的网络。
  • 他让A、B、C类地址的主机地址部分用作子网地址,可以将原网络分为多个物理网络的一种机制
  • 每类的都有自己默认的网络地址
类别 子网掩码
A 255.0.0.0
B 255.255.0.0
C 255.255.255.0
  • 通过和IP地址进行运算(1&0=0;0&0=0;1&1=1)来得到网络号,这里的操作需要将IP地址转为二进制在进行

为什么细分了网络?

从上面的图,我们可以看出,每类地址的网络分段

  • 题目
    • 1、10.0.0.1和10.1.1.1的网络号相同吗?
    • 2、172.16.0.1和172.16.1.1的网络号呢?
    • 3、192.168.10.103和192.168.0.102呢?
  • 答案
    • 1、相同。首先我们知道这两个IP地址同属A类,再将他们和默认子网掩码(255.0.0.0),得到结果两个都是10.0.0.0,这就是他们的网络号,也正好符合图中的前8位,10转为二进制就是00001010
    • 2、同理可得,属于B类,相同,并且网络号为172.16.0.0
    • 3、属于C类,网络号不同,分别为192.168.10.0192.168.0.0

上面的题目都是在默认的子网掩码之下,那么如果我们改了子网掩码呢?

  • 题目
    • 1、172.16.0.1和172.16.1.1的子网掩码是255.255.255.0,此时网络号相同吗?
  • 答案
    • 1、不同,此时我们在算一次,把每个IP地址都和255.255.255.0,此时网络号分别为,172.16.0.0172.16.1.0,则不同。
  • 我们可以看到经过子网掩码,把我们本来相同网段IP地址,划为不通网段的地址,这样就细分了网络,有更多的物理网络

IP分片

当我们的MTU最大传输单元(1500字节,去掉以太网首部,就是1480字节)满足不了我们的需求时,我们就需要IP分片(分成一片片传输)。

  • 回顾IP协议组成中的:标志字段、片偏移
    • 16位标识()IP分片时,该值被复制每一个分片中,相当于每个分片的id
    • 三位标志
      • 首位:保留字段,一般为0。
      • 中间位:不进行IP分片时为0,进行时为1。
      • 末位:假如此时有3片IP分片,前两片末位都为1,最后一片末位为0。
    • 13位片偏移:该片偏移原始数据包开始处的位置。假如此时5片IP分片,那么第一片的13位片偏移为1,第二片为2,让路由知道先后顺序

  • 错误处理
    • IP分片时,只丢失一片数据,也需要重传整个IP数据报。
    • 当给定数据报的第一个数据报片到达时,开始定时器过期丢弃所有数据报片。

ICMP协议

  • 属于IP协议的一部分
  • 确认 IP 包是否成功送达目标地址,通知在发送过程当中 IP 包被废弃的具体原因,改善网络设置等。
  • IP包首部有一个字段TTL,每经过一个路由器就会减1,直到减到0时IP报就会被丢弃。
  • 此时,IP路由器将会发送一个ICMP超时的消息给发送端,通知该包已被丢弃
  • traceroute命令的原理就是通过ICMP超时消息来显示发送主机到达特定主机之前经历了多少路由器。

总结:

  • 处理数据报在网络中的行为(路由选择)。
  • 承载端到端的数据交互方式(两个ip的host之间的传递数据)。
  • 缺点:
    • 只是保证数据基本达到,数据可能是无序的。
    • 可能是缺失的。

传输层(TCP协议)

解决IP层的痛点,是一种安全的协议,主要通过连接疏通了整一个通道,安全传输。

三次握手和四次挥手

三次握手

  • 看前三个箭头
    • 客户端发送SYN A1请求建立连接,SYN就是synchronization(同步),而且此时A1是被传在sequence(序列)中的,此时服务端接收到客户端传来的A1信号。
    • 服务端回应客户端我接收到了,所以发送ACK A2(只是确认应答,所以只需在原有的A1+1=A2),这里的ACK就是acknowledge(确认)。并且请求客户端建立连接, 此时发送一个信号SYN B1
    • 客户端接受并确认应答,告知服务端接收到了信号,所以发送ACK B2(因为上次推过来的SYN B1)

四次挥手

  • 看后四个箭头
    • 客户端发送结束信号FIN C1
    • 服务端接收到结束信号,回应接收到了,此时发送信号ACK C2,客户端已经关闭,但是服务器处于半关闭状态(客户端不能向服务器发送请求,服务器还是能接受客户端请求)
    • 服务端向客户端发送结束信号FIN D1
    • 客户端接收到结束信号,回应接收到了,此时发送信号ACK D2,服务器也关闭。

通过序列号与确认应答提高可靠性

  • 序列号是按照顺序给发送数据的每一个字节(8位字节)都标上号码的编号。接收端查询接收数据TCP首部中的序列号数据的长度,将自己下一步应该接收的序列号作为确认应答返送回去。通过序列号确认应答号,TCP能够识别是否已经接收数据,又能够判断是否需要接收,从而实现可靠传输。

重发超时的确定

  • 重发超时是指在重发数据之前,等待确认应答到来的那个特定时间间隔。如果超过这个时间仍未收到确认应答,发送端将进行数据重发。最理想的是,找到一个最小时间,它能保证“确认应答一定能在这个时间内返回”。
  • TCP 要求不论处在何种网络环境下都要提供高性能通信,并且无论网络拥堵情况发生何种变化,都必须保持这一特性。为此,它在每次发包时都会计算往返时间及其偏差。将这个往返时间和偏差时间相加,重发超时的时间就是比这个总和要稍大一点的值。
  • 在 BSD 的 Unix 以及Windows系统中,超时都以0.5秒为单位进行控制,因此重发超时都是0.5秒的整数倍。不过,最初其重发超时的默认值一般设置为6秒左右。
  • 数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长
  • 此外,数据也不会被无限、反复地重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接。并且通知应用通信异常强行终止

以段为单位发送数据

  • 在建立TCP连接的同时,也可以确定发送数据包的单位,我们也可以称其为“最大消息长度”(MSS)。最理想的情况是,最大消息长度正好是IP中不会被分片处理的最大数据长度。
  • TCP在传送大量数据时,是以MSS的大小将数据进行分割发送。进行重发时也是以MSS为单位。
  • MSS在三次握手的时候,在两端主机之间被计算得出。两端的主机在发出建立连接的请求时,会在TCP首部中写入MSS选项,告诉对方自己的接口能够适应的MSS 的大小。然后会在两者之间选择一个较小的值投入使用。

利用窗口控制提高速度

  • TCP 以1个段为单位,每发送一个段进行一次确认应答的处理。这样的传输方式有一个缺点,就是包的往返时间越长通信性能就越低。
  • 为解决这个问题,TCP引入了窗口这个概念。确认应答不再是以每个分段,而是以更大的单位进行确认,转发时间将会被大幅地缩短。也就是说,发送端主机,在发送了一个段以后不必要一直等待确认应答,而是继续发送
  • 窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。这个机制实现了使用大量的缓冲区,通过对多个段同时进行确认应答的功能。

总结:

  • 抽象出连接的概念,在一个TCP连接中,仅有两方彼此通信
  • 保证了可靠数据传输及正确顺序的数据处理
  • 提供流量控制(Node.js中的流)

应用层(HTTP协议)

我会留到下一篇再讲,同时我会结合node来讲解其中的http的应用和原理,敬请期待。