IP和以太网的收发操作
上面的部分比较贴近TCP协议的相关操作,TCP完成连接收发的同时其实都需要IP模块的配合,在了解这两个模块如何配合工作之前需要了解完整的网络包是如何组成的。
包的组成
对于任何一个网络包,都有最外层的抽象概念,那就是头部和数据 两个部分
上面的部分有一个这样的图,里面套接字中的TCP数据,这里需要注意在TCP控制信息的前面就是以太网和IP的控制信息,对于只传输控制信息的网络包虽然没有数据的部分,但是可以把协议的头部信息作为数据部分。
通过下面的图也可以发现,所有的网络包必须要委托以太网和IP控制信息才能完成传输。
把存放数据的网络包进行拆分,可以看到下面的TCP/IP 包结构:
我们可以简单把头部和数据看做是平时的快递,头部是面单,指示从哪里到哪里,然后这个“快递”会通过网络转发设备的查表操作判断传输到那个方向。
转发设备是什么?这里建议看看第一章的关于认识网络传输的基本概念,这里简单提一下:
- 路由器根据目标地址判断下一个路由器的位置
- 集线器在子网中将网络包传输到下一个路由
但是实际上集线器和路由器各自有不同分工,集线器负责管理以太网规则传输包设备,路由器管理IP转发规则,所以上面两个步骤也可以做下面的理解:
- IP协议根据层级规则判断下一个IP转发设备。
- 子网的以太网协议转发给下一个转发设备。
实际上头部部分应该分为 MAC 头部 和 IP头部。为什么要把头部拆分为两个协议?实际上是为了让协议之间可以实现替换,比如MAC可以替换为局域网、ADSL、FTTH。同时因为互联网这样庞大的网络架构,需要更加细化的分工。
小结
实际上网络包的封装应该范围三个部分:
第一部分是TCP模块组织头部信息和数据包(当然也可能没有数据只有控制信息)。
第二部分是把整个TCP模块塞到IP模块的后面,然后经过网卡发送出去。
第三部分是在IP模块前面加上Mac信息。
名词解释ADSL:可以理解为以前宽带使用拨号连接互联网上网的方式。
非对称数字用户线路(英语:Asymmetric Digital Subscriber Line)又称非对称数字用户环路(Asymmetric Digital Subscriber Loop),简称ADSL。ADSL是一个依靠铜质电话线的数据传输技术比传统的调制器更快。
FTTH:其实就是现在的光纤通信。
光纤到户(英语:Fiber To The Home,缩写:FTTH)是一种光纤通信的传输方法。是直接把光纤接到用户的家中(用户所需的地方)。
这种光纤通信方式及策略与FTTN、FTTC、HFC(Hybrid Fiber Coaxial)等也不同,它们都是需要依赖传统的金属电线,包括双绞线及同轴电缆等,作“最后一哩”的信息传输。
IP 协议头部
IP类似快递上的单号,所以实际上IP模块是无法决定自己选择正确的地址了,哪怕应用程序通过TCP告诉IP发的地址式是一个错误地址,IP也无法自行修正只能照做。
从这样的特点可以看出IP头部又有点类似快递员,和网上买东西商家发错地址或者我们填错地址一样,不能把责任赖在快递员上。
IP协议头部的组成类似下面的结构,注意IP地址的长度固定需要32Bit的空间占用。
这里需要注意“发送方的IP”地址不是指计算机的IP,而是指网卡对应的IP,因为IP不是分配和计算机而是网卡的,当一个计算机有多个网卡就会存在多个IP。
那么应该如何判断包发送给哪一个网卡?这里涉及到IP协议规则,无论是路由器的转发还是协议栈的处理都需要按照IP协议转给下一个用户。
查询分配给哪一个网卡在不同操作系统中的查询方式不同,查询发送端需要查询是哪个网卡把包发给了路由器,这个动作只需要简单的根据路由器IP地址和网卡的IP进行比对。
在windows中可以通过命令
route print
查看路由信息。
获取IP和网卡之后,还需要知道包所属的协议,委托内容是固定的,比如TCP模块就是06,UDP就是17,大部分请求都是HTTP,使用TCP的方式传输。
以太网Mac头部
TCP/IP模块只能在传输层上互相了解,但是往下的链路层以太网用同样的规则是行不通的,所以头部加上TCP/IP的头部之后,还需要在头部加上Mac头部,Mac头部包含了发送方和接收方的Mac信息,这里可以简单理解为Mac和IP的作用类似,不过Mac头部是48Bit,而IP头部是32Bit。
需要注意以太类型就是Mac包装的后面的真实数据的类型, 如果是IP就是IP协议。另外需要注意在发送Mac包给接收方之前,由于不知道对方的Mac地址,所以还需要一步查询操作。
注意IP 模块根据路由表 Gateway 栏的内容判断应该把包发送给谁。
下面是Mac头部的组成:
查询Mac地址
查询对方的Mac地址需要用到ARP( Address Resolution Protocol,地址解析协议),ARP通过广播的方法查找到目标地址,所谓广播就是字面意思把消息发给所有的其他互联网用户,等待对方应答。
为了防止每次查询都要带ARP的数据,所以有一块ARP的缓存专门缓存这个地址,但是需要注意这个缓存和IP模块的IP地址一样,过一段时间会被ARP缓存淘汰掉,但是如果IP刚刚变化可能会导致ARP缓存未及时更新导致网络异常。
实际整个工作都是由IP模块完成的,虽然Mac地址是以太网数据传输的必要内容,但是实际上让IP模块负责这些工作是有利的。
为什么需要以太网?
以太网基本知识
首先来看看以太网的基本发展,虽然设计结构越来越精细,但是本质上干的活却没有发生变化。
以太网早期原型本质上可以看作是一根网线以及一个用于收发的设备,网络信号发送之后通过广播最终到达所有设备,在开头的收发信息让其他人可以知道信息最终要发给谁,在Mac头部就包含了“收货地址”,而具体发送了什么类型的可以通过上面的“以太类型”进行判断。
以太网在后续的发展中将主干网线替 换成了一个中继式集线器,收发器变成双绞线,虽然形式变了,但是本质的工作没有变。
以太网到了现代最终由交换式集线器完成所有的操作,并且网络请求只有请求方和接收方可以互通,集成度增加以及网络传输安全性能增加。
但是以太网无论怎么发展性质始终没有任何变动:
MAC 地址代表的目的地,用发送方 MAC 地址识别发送方,用以太类型识别包的内容。
IP模块转光(或电)信号
网络信号发送依赖网卡,但是网卡并不是插上电就可以使用的,还需要依赖初始化以及驱动程序才能完成操作,驱动程序和初始化操作在其他很多电脑硬件中比较常见,但是以太网有比较独特的驱动操作,那就是控制以太网收发操作的MAC当中收发MAC地址。
另外网卡还有一个特性是网卡的 ROM 中保存着全世界唯一的 MAC 地址,这是在生产网卡的时候就已经决定。
所以可以看到最终完成IP数据转化的关键是驱动程序,网卡中保存的 MAC 地址会依赖网卡驱动程序读取并分配给 MAC模块。
网络包的控制信息
MAC模块工作在网卡调用MAC包发送请求命令之后,MAC模块的工作是划分网络包的“边界”。
为了划分边界,MAC模块会加上三个控制信息:
- 报头:是一串像 10101010…这样 1 和 0 交替出现的比特序列,长度为** 56 比特**,它的作用是确定包的读取时机。
- 起始帧分界符(SFD):确定帧的起始位置,主要是辅助电信号切分报文头部和真实的网络包边界,并且判断出每个比特的界限。
- FCS:检查包传输过程中因噪声导致的波形紊乱、数据错误,它是一串 32 比特的序列,是通过一个公式对包中从头到尾 的所有内容进行计算而得出来的
响应内容传输从IP给TCP
当服务器接收到网络包之后,首先协议栈会判断以太网头部的以太类型,发现是0800为TCP/IP协议,接下来是IP模块工作,首先是检查IP头部是否正确,IP地址是否正确。
如果接收方是window客户端,因为不会对包进行转发,如果发现包不是发给自己的,会调用ICMP消息回传给请求发送方,IMCP的消息格式如下:
另外接收到的网络请求可能会因为数据包过大出现IP分片,分片的包会在 IP 头部的标志字段中进行标记,IP模块会把分片过的包暂存内部内存空间,等相同ID的包全部接收到缓冲区之后再拼接。
怎么保证拼接的顺序正确呢?可以查看前文IP 头部还有一个**分片偏移量(fragment offset)**字段,它 表示当前分片在整个包中所处的位置。
IP模块完成数据分片重组之后,数据包交给TCP模块操作,TCP还会再次检查一遍请求方和接收方的IP信息,以及获取端口号找到对应的套接字,找到套接字之后根据应用程序的类型进行不同的操作,这个过程可能是建立连接,也可能是完成应用程序数据的读写操作。
这里可能会觉得IP检查不是IP模块的操作么,TCP去看IP模块的信息是不是“越权”了?实际上这是一种性能开销都考虑而违反“迪米特法则(Law of Demeter)”的一种特例。因为TCP模块需要频繁使用IP模块的信息,如果老是需要数据之间的交互传输非常影响性能。
UDP协议收发操作
TCP/IP为了保证数据准确收发需要使用一系列复杂的模块和过程配合保证数据的完整传输,但是有时候有些应用程序为了保证高效会舍弃使用TCP这种复杂的机制。
UDP协议的要点是尽可能将所有的数据通过一个包解决,UDP 没有 TCP 的接收确认、窗口等机制,因此在收发数据之前也不 需要交换控制信息。UDP的实现非常简单只需要应用程序加入头部,直接交给IP模块完成即可,接收方也只需要检查IP头部的发送方和接收方的IP地址信息,然后再从UDP找到端口号,最后再找到套接字信息把数据给应用程序。
因为UDP不保证传输的稳定性所以无论包是否接收到都无关紧要,只要对方没有回应直接把包进行重发即可。这种不需要保证传输稳定性的场景还是有不少的,比如聊天数据、音频和视频信息,即使丢失一点点也没有关系,最多是卡顿一下而已。
关键:UDP 可发送的数据最大长度为 IP 包的最大长度减去 IP 头部和 UDP 头部 的长度。一般来说 IP 头部为 20 字节,UDP 头部为 8 字节,因此 UDP 的最大数据长度为 65507 字节。
下面是UDP的头部信息:
小结
在第二章我们了解Socket链接的步骤和大致细节,另外介绍了整个互联网比较重要的两个协议TCP协议和IP协议,在两个协议中需要重点掌握头部设计,IP模块完成TCP模块的数据,TCP数据封装应用程序数据,之后还需要配合Mac以太网模块完成网络包的最后封装,等一切准备工作完成之后,由网卡以及驱动程序把整个包发送出去,所以其实可以看到决定你能不能上网等实际上是网卡和驱动(这不是废话),但是这些内容属于不同层级的内容,需要一一消化。
介绍了TCP之后,在在第二章最后部分简单提到了UDP协议,UDP是一种简单暴力的协议,设计的目的是让所有的数据尽可能通过一个包完成,所以他不需要链接也不需要保证数据安全传输,数据丢了直接传输即可,UDP的应用也是十分广泛的,比如游戏,视频,音乐等等数据的传输,很多时候丢一点根本无关紧要,因为即使找回来这些数据也没有意义。
TCP/IP连接也只是互联网数据传输的一小部分,但是确实最为核心的部分,虽然往下还有以太网和网卡以及网络通信如何上网等细节,但是只有深刻了解TCP/IP协议才能了解整个互联网是如何交互和数据传输的。