这里要说的东西,还是建立在上一篇的TCP/IP四层模型之上的,主要讨论分析协议栈的各个层包头结构,了解TCP/IP数据包头的组织形式。首先看一张图,


wKiom1i8GInAQ43_AAHx1ijzafc003.png

    这张图反应的是数据的整个接收的流程,接下来我们就从下向上,一次说明每个包头结构。


以太帧头

wKioL1i8GZSi3CMsAADoN-gdKSI757.png

     这里的目标地址和源地址都指的的MAC地址,也就是网卡的硬件地址,都是占6个字节,48位,通常用12个十六进制数表示,如 08:00:20:0A:8C:6D, 这个在网卡出厂是已经固化,具体内容之后会提到。

     帧类型有三种,IP、ARP、RARP。如图所示,以太帧数据长度范围为46~1500字节,其中1500字节叫做以太网的最大传输单元MTU,不同网络类型的MTU值不同。ARP和RARP的数据包长度不足46字节,因此在数据段后面补充18字节作为填充;当数据包的长度大于MTU时,需要对数据包进行分片,也就是我们常说的IP分片 ,这个操作在网际互联层(IP层)实现。

     帧末尾是CRC校验码,在数据链路层广泛使用了循环冗余校验(CRC),关于CRC具体实现,我们暂且不谈。我们需要知道的是在数据链路层若仅仅使用CRC差错检测计数,只能做到对帧的无差错接收,但我们并没有要求数据链路层向网路层提供“可靠传输”的服务。

     两个字节的类型,就是上层协议的类型,用来判断交给上层那种协议。


ARP数据报格式

     在网络通信的过程中,通常源主机都是知道目的主机的IP地址和端口号,来进行通信的。但我们又知道,当在一个局域网内的时候,只有MAC地址才能唯一标识找到某个主机,(MAC地址是硬件物理地址,在网卡设备出厂时就已经写死 )在同一局域网内的两台主机,如果知道MAC地址,可以直接通信。我们发送的数据包,首先都是要被网卡设备接受之后,如果MAC地址匹配,才能向上层传递,处理上层协议,但如果MAC地址不符,该数据包将直接被丢弃,因此,在通信之前,我们必须获得目的主机的MAC地址。ARP协议 就是起这个作用的。

     ARP协议又叫做地址解析协议,是在局域网内的一种协议,可以通过IP地址查询到MAC地址。首先看ARP数据报格式:


wKiom1i8GgCx5a5BAABALtVWWjk493.png

这个是在上面以太帧的基础之上的,红色表示该段的数据大小,单位是字节。


首先对各个段做简单解释:

     以太网目的地址和以太网源地址都指的是MAC地址,均为6字节,各48位;

     帧类型:由于这里是ARP协议,帧类型为0806(以太帧头中有说明)

     硬件类型:链路层网络类型,即硬件接口类型,1表示以太网

     协议类型:高层协议类型,即要转换的地址类型,0x0800为IP地址

     硬件地址长度 和 协议地址长度:分别用一个字节来表征物理地址和Ip地址的长度,以太网的地址长度为6字节,IPv4的地址长度为4字节,IPv6的地址长度为6字节。实现了ARP报文可以在多种硬件和不同网络协议之间进行传递。

     op:1表示ARP请求, 2表示ARP应答。

     由于ARP数据报长度不足46,因此会补充一定的位,ARP数据报是定长28位的,因此不需要单独设置标志位指明ARP有效位数。

     ARP协议是工作在网络接口层的,是一种管理协议,上层无从知晓。

举个栗子

     现在有两台主机,主机A,和主机B,主机A的IP地址为IP1, MAC地址为M1;主机B的IP地址为IP2,MAC地址为M2。现在主机A想向主机B发送信息,但只知道B主机的IP地址和端口号,已知主机A已经通过路由器找到B主机所在的局域网,接下来通过ARP获取B主机的MAC地址,实现通信。

     有一点我们需要注意的是,ARP在MAC帧的上层,在ARP的数据包中,没有保存的上层信息,因此,ARP不需要继续向上层传递任何信,也就是说ARP的整个过程不会被用户看到,是由操作系统完成的。

 通信过程:

     1、首先主机A发起ARP请求,相对于的ARP数据报格式为

     FF FF FF FF FF FF   M1  08 06  00 01  08 00  06  04  00 01  M1  IP1  00 00 00 00 00 00  IP2

     首先,由于不知道该数据报要发送给哪个主机,因此采用的是广播的方式,也就是一开始的以太网目的地址为 FF FF FF FF FF FF;M1表示主机A的物理地址;0806表示该数据包树ARP数据报;00 01表示以太网,08 00 表示采用IP协议(IPv4);06 ,04表示的是MAC地址和IP地址长度;00 01表示该ARP数据报是请求信号;之后地址这里不解释。

     2、由于主机A是以广播的形式将该数据报发出,因此,该局域网内的所有主机都可以收到该数据报,接收到数据报之后,由网络接口层对对以太帧头进行分析,发现该数据报是一条广播信息,可能是发给任何一台主机的,又因为该帧类型为0806,表示这是一个ARP数据报,因此网络接口层解包之后,直接将有效载荷传递给上一层ARP,交由ARP来处理该数据报。

     3、ARP发现该数据报的op位是1,表明这是一个请求,(关于类型检测这里不关注)然后去后面找该ARP请求的目的IP地址,如果和自己的IP地址不同,则直接将该数据报丢弃;如果相同,ARP会生成一条新的ARP数据作为应答,并传递给下一层封装,之后完整的ARP数据报为

     M1  M2  08 06  00 01  08 00  06  04  00 02  M2   IP2   M1  IP1

   和请求的ARP数据报类似,我们需要关心的是,这时op变为了00 02,表明该数据报是一个应答信号;在以太帧头部,已经将主机B的MAC地址和主机A的AMC地址封装,可以直接和主机A进行通信(当然这里的直接通信并不是局域网内的其他主机不会收到该消息,而是其他主机会由于一开始的目的MAC地址不同,而直接过滤掉该数据报);在该数据报末,封装了主机A和主机B的MAC地址及IP,这些信息是提供给主机A的。

     4、主机A接收到该数据报之后,进过网络接口层进行解包,将有效载荷传递给上层ARP来处理,主机A仅仅将该数据报做一般的ARP数据报处理,发现op位为00 02,得到该ARP数据报为应答信号,在数据报末得到自己的IP,表明这是一条给自己的应答信号,从而和之间发出的ARP请求对应,获得了主机B的MAC地址,之后就可以直接和主机B进程通信。

     上面详细说了关于ARP请求如何实现IP地址到AMC地址的转化,可以发现,ARP是向整个局域网请求。

     同时还要提到的另外一种协议叫做RARP,是用来实现MAC地址到网络地址的转化,这个过程相比ARP就显得更加容易,因为已经获得了MAC地址,在局域网内已经可以实现相互通信,这里不在赘述。

     总而言之,ARP是通过IP发送请求的一种机制,从而间接获取MAC地址的一种方式。

如果源主机和目的主机不在同一网段,ARP请求无法穿过路由器,源主机如何和目的主机通信?

     答:源主机和目的主机不在同一网段内,说明这里需要用到路由器,但源主机的ARP请求不能穿过路由器,做法如下:主机A首先将本局域网内的路由器R1的IP地址转化为硬件地址M3,以便将IP数据报传送到路由器R1;之后R1从转发表找到下一跳的路由器R2,同时使用ARP解析出R2的硬件地址M4;于是IP数据报就按照硬件地址从M3转发到了路由器R2;R2在转发IP数据段时,采用类似办法解析出目的主机的MAC地址M2,是IP数据最终交付给主机B。


IP数据报格式(IPv4)

wKioL1i8GrrzsoGIAABLs-bk4Rw290.png


各字段含义:

     版       本:占4位。要求通信双方的版本必须一致,现在以IPv4为主,IPv4该字段值为4;

     首部长度:占4位 。在上图可以发现,每行32位(4字节),即宽度为4字节,IP包头的长度最小为20字节,因此,首部长度最小为5。4字节可以表示的最大值为15,因此IP包头最大长度为60字节;

     服务类型:占8位。一般不使用,只有在区分服务时,该字段才起作用;

     总  长 度:固定20字节+选项+数据的总长度,共16位,因此IP数据报的最大长度为(2^16-1 )字节

     标      识:占16位。是IP在存储器中维护的一个计数器,每产生一个数据报,计数器加1 ,该值并不标识序号。当数据报长度超过MTU时,必须进程IP分片,被分片的所有数据报的标识字段都被赋予了该计数器值,也就是说,该字段相同的数据报,是同一数据报分片得到的,这将是最后重组的依据。

     标      识:占3位。第一位MF = 1,表示后面没有后面还有分片的数据报片,MF= 0,表示当前数据报片是分片之后的最后一个;第二位DF = 1,不允许分片,DF= 0,允许分片;第三位没有意义;

     片  偏 移:占13位。用来确定被分片的数据片的相对位置,方式片段重组的时候发生混乱;

     生存时间:TTL,占8位。表征数据报的寿命,防止无法交付数据报,导致互联网上存在过多的没有宿主的游离态数据报,这里的生存时间并不是以时间为单位,而是以经过路由器的跳数,经过一个路由器,TTL值减一,减到0时,生命结束,数据报被丢弃;

     协      议:占8位。标志数据报携带的数据是何种协议,TCP、UDP、ICMP、IGMP;

     校  验 和:只校验数据报首部,不包括数据部分。因为每经过一个路由器,都需要校验一次,数据校验交给更高层协议负责,可以减少工作量。

     整个IP数据报的实现,是采用了位段的方式实现的,

     IPv4由于有可选项存在,因此我们说IPv4在每次传递数据的过程中都需要预先进行判断,IPv6使用的是定传包头,这就导致了IPv4 比IPv6的传输速度慢。



IP地址与路由


 IP地址的特点:

     1、每一个IP地址都是由网络号和主机号两部分组成。IP地址是一种分等级的地址结构,网络号由ISP分配,而主机号由得到该网络号的分组自行分配;

     2、IP地址是标志一个主机(或路由器)和一条链路的接口。一个路由器至少应当有两个不同的IP地址,路由器每一个接口都有一个不同网络号的IP地址;

     3、一个网络是指具有相同网络号的主机的集合,具有不同网络号的局域网必须使用路由器进行互联;

     4、在IP地址中,所有分配到网络号的网络都是平等的。

    IPv4的IP地址长度为4字节,采用点分十进制表示法,形如 192.168.0.1 的格式。

     

IP地址可分为A~E五类:

A类0+7位网络号+24位主机号0.0.0.0~126.255.255.255
B类10+14位网络号+16位主机号128.0.0.0~191.255.255.255
C类110+21位网络号+8位主机号192.0.0.0~223.255.255.255
D类1110+28位224.0.0.0~239.255.255.255多播地址
E类11110+27位240.0.0.0~247.255.255.255保留未使用

127.*网段之后127.0.0.0一个IP地址可用,代表当前主机。

     最早的划分方式,造成了对P资源的很大浪费,大量的组织申请B类网络地址,导致B类很快黑申请完,但A类地址被大量浪费。同时对于B类网络,一个网络中有大量主机,路由器压力相当大, 为解决这些问题,提出了新的划分方案CIDR(子网划分)。

     CIDR的划分方式是建立在子网掩码的基础之上的,与之前的ABC类无关,网络号和主机号的划分需要用一个额外的子网掩码来表示,而不能IP地址本身决定。

     使用子网掩码的方式,对于网络的扩展是十分方便的。

网络地址 = IP地址 & 子网掩码

广播地址 = 将子网掩码中0对应的网络地址全部换成1 (可以简单理解为最大的网络地址)

网络地址在整个网络上是唯一的,主机号为0,表示网络地址,主机号为全F,表示广播地址


举个栗子

IP地址172.16.1.200
子网掩码255.255.0.0
网络号176.16.0.0
子网范围172.16.0.0 ~ 172.16.255.255
广播地址176.16.255.255


一些特殊的IP

    如果一个组织内部建立局域网,IP地址只用于局域网内部的通信,不直接连接到Internet上。网络IP在整个网络上是唯一的,私有IP是不会出现在公网上的,也就是说,在每个局域网内可能都有一个私有IP是192.168.0.111,但这个IP仅在当前局域网内可见,我们可以使用局域网代理的方式,实现多个相同的私有IP共同存在。

     这些依靠nat技术(网络地址转换)/代理服务器实现。

     RFC规定了用于组建局域网的私有IP地址,不会出现在Internet上,有如下:

          10.*                                                                                                                                 

          172.16.*~172.31.*                                                                                                          

          192.168.*                                                                                                                        

这些地址用来当做局域网IP,没有主机是直接通过这些ip访问外网的。

    除了上述私有ip外,还有其他特殊的ip地址,如下:

     127.*的IP地址用来本地环回(loop back)测试,通常是127.0.0.1。本地环回测试,数据不会发送到网络上,而是自己发送自己接收,通过环回设备再发回给上层协议和应用程序,贯穿协议栈,用于本地测试。

wKiom1i8G8Xjw8CjAAU0yQHOee8424.png

     数据报从网络上抓取到之后,在内存中也会针对该报文创建一系列的数据结构来维护它,一个典型的数据结构叫做sp_buf,定义了一个缓冲区,将所有的数据放到缓冲区中。

     本地环回通常用来进行应用方面的测试!(整个环回过程,除了应用层之外,都是由内核完成的)



路由(route)

     路由是网路信息从信源到信宿的路径,指路由器从一个接口上收到数据包,根据数据报的目的地址进行定向并转发到另一个接口的过程。

     路由和桥接相比:桥接是发生在数据链路层的,而路由是发生在网络层的,这就注定了二者在传递信息的过程中使用的是不同的信息。

     路由的前提条件是路由表已经建立好,路由表生成算法最终目的是让我的路由查找是趋向于收敛的。

     路由其实就是查找路由表的过程,路由工作包含两个基本的动作:

     1、确定最佳路径(复杂)

     2、通过网络传递信息(相对简单)


路由重点名词

    路由结点

     一个具有路由能力的主句或路由器,它维护一张路由表,通过查询路由表来决定向那个接口发送数据包;

    接口:

     路由结点与某个网络相连的网卡接口,一个路由器至少有两个接口;

    路由表

     由很多路由条目组成,每个条目都指明去往某个网络的数据报应该经过那个接口发送,最后一条是缺省路由条目;

route     # 查看当前主机的路由表

    路由条目

     路由表中的一行,每个条目主要由网络地址、子网掩码、下一条地址、发哦少年宫接口四部分组成,如果要发送的数据包的目的网络地址匹配路由表中的某一行,就按规定的节酷发送到下一跳地址;

    缺省路由条目

     指明信息包的目的地不在路由列表中时的路由。子网掩码为0.0.0.0,

当一个数据报发送给路由器之后,路由器可能的三种回复方式:

    1、知道怎么走(数据报在哪个网络)

    2、知道谁知道(其他路由器知道该数据包应该在哪个网路 )

    3、就在这个网络(该数据报就在我当前网络)

[muhui@MiWiFi-R1CL-srv ~]$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.31.0    *               255.255.255.0   U     1      0        0 eth0
192.168.56.0    *               255.255.255.0   U     1      0        0 eth1
127.0.0.0       *               255.0.0.0       U     1      0        0 lo
default         192.168.31.1    0.0.0.0         UG    0      0        0 eth0

  Destination:目的网络地址(和当前路由器直接相连的目标网络)

     Gateway:下一跳地址

     Genmask:子网掩码(当前Iface接口对应的子网掩码)

     Flags:U(表示此条目有效,可以禁用某些标志);G(此条目下一跳地址为某路由器,没有G选项则表明下一跳不是路由器,不需要再经过路由器转发)

     Use Iface:接口

路由器是如何路由的?

     假设要发送的数据包目的IP为IP1,IP1的首先跟第一行的子网掩码做与运算,判断运算结果是否等于目的网络地址;

     如果相同,表明该数据包就在该网络中,则将该数据包从该条目对应的端口发出,不再经过路由器;如果不同,则继续跟第二行的子网掩码做与运算,直到倒数第二行也不匹配;

     如果数据包的IP地址所在网络与之前的都不匹配,则发送到缺省路由条目对应的端口号,由下一个路由表决定下一跳的地址。

注意:

     1、我们使用个人PC机调用route命令时,除了默认条目,这里仅仅只有一条路由条目,这是因为我们的笔记本也相当于一个路由器,但是仅仅只有一个端口,但对于路由器而言,至少有 两个端口。

     2、上面列出的四条路由列表中,第一条是当前路由器所在网络对应的条目,属于情况3;第2、3条属于数据报的网络地址可以在当前的路由列表中查询到,也就是和当前路由器相连,属于情况2;最后一条路由器知道自己不知道,但是缺省路由条目应该知道,属于情况1。

     3、理论上应该还存在这样一种路由条目信息,该条目并不属于缺省路由条目,但是Flags也为UG,表明,当前路由器知道该IP数据报在这个路由器中可以查到网络位置。

     站在应用层的上面,IP层是没有网路差异的,这些工作完全是由下层解决的,因此IP协议是整个互联网的基础,实现了不同的网络直接使用一套协议就可以全方位地工作,是一整套的虚拟化技术。通过软件方式,屏蔽物理差异。

     任何逻辑和任何差异都可以通过一层软件来实现,这就是虚拟化技术。




传输层协议

     TCP、UDP 通过端口号判断将有效载荷交给上层哪个进程或作业。(这里没有再标志需要交给哪个协议,因为传输层上层是应用层,应用层协议过多)

     端口是用来表示主机上的唯一进程的。

     不管是UDP还是TCP,将来都是在IP数据报中包裹着的,这些信息在路由过程中不会发生任何变化。

     IP+ 端口:socket,标识互联网上的唯一进程

常见端口号

     FTP:文件传输协议。20->数据传递端口;21->命令传输端口;

     SSH:安全shell协议。端口号22;

     telnet:远程登录协议。端口号23;

     DNS:域名系统。端口号53;

     http:超文本传输协议。端口号80;

     https:安全的http协议。端口号443;【了解ssl】

     SMTP:简单邮件传输协议。25->发邮件端口号 ;

     POP3:邮局协议。110->收邮件端口号;

     mysql:数据库。端口号3306 ;

/etc/services     # 列出了所有的well-known的服务端口和对应的传输层协议。


UDP


wKiom1i8HJPT3RQoAABOIQ9MaxI157.png   首部长度定长,因此这里不需要单独的字节表明首部长度多少位以供分离包头使用。


TCP

     MAC帧负责在局域网内,将数据从A主机传到B主机;IP层负责数据报并不安全地从A主机的IP层传到B主机的的IP层。

     IP层在路由过程中不保证数据传输的可靠性,数据包的丢失,数据包的重传等问题都需要传输层处理。IP层负责的是通过路由找到,而传输层是负责找到后如果出现问题,该如何处理。

wKiom1i8HLrCY9WvAABLGd4IELU544.png

     源端口和目的端口:这里不再解释;

     序列号和确认序列号:保证信息传输的可靠性。如果发送端一次性发送了大量数据,接收端只会将最新的一次的确认号返回,表示该数据包之前的所有数据都已经收到;<接收端返回的TCP包头中的确认序号与发送端发送的TCP包头中的序号一致>

          IP层的16位标识等信息是用来保证数据分片并重新组合的,对于传输层而言,根本不知道分片的整个过程。也就是说,在传输层看来,数据一直是完整的,不论是打包交给IP层的时候,还是IP解包之后上传回来。

          可靠性机制:如果没有得到响应,就无法知道信息是否被收到,只要收到响应,就可以确定信息被收到;可以通过序号确认是否发生丢包。

          网络上不存在百分百的可靠性。

     首部长度:和IP包头一样,TCP包头最小20字节;

     如果一次发送多个TCP数据报,会应答最新的数据报序号,表明该序号之前的所有TCP数据报均正确到达。

序号:

      数据丢失,重发;阻塞导致

窗口大小:

     少量丢包时,重传是十分有效的一种方式;大量丢包,可能是由于网络环境的问题,乳沟一直重传,会恶化网络环境。

    拥塞避免:大面积丢包问题,叫做网络拥塞。最好的办法是等待,等待网络环境改善;慢启动,快重传算法实现。

     流量控制:《窗口大小》发送数据过大,但接收方缓存区太小,或发送数据太快,导致大面积丢包,可能使发送方认为此时网络环境差,从而使用拥塞避免算法。为了避免这种情况的产生, 引入了窗口大小的概念。这里的窗口大小就是上面提到的接收方缓冲区的大小。有了窗口大小的概念,就可以实时报告自己的接收能力,控制发送数据的节奏。


 TCP的可靠性保证有如下几点:

          超时重传,请求应答,流量控制,拥塞避免。

    TCP的面向链接是提供可靠性的一种前提。TCP内部维护了四种计时器,《TCP/IP羊皮卷》


TCP中的六位标志位:

    URG:0(16位紧急指针无效),1(紧急指针被触发,紧急数据不用在接收队列中排队);

    ACK:确认序号,大多数情况被设置为1;

 PSH:为1时,将缓冲区中排好序的数据直接交付给上层,而不用等待缓冲区写满再交付

 RET:1(链接恢复 ,断开并重新连接),还可以用来拒绝非法报文段或拒绝打开链接;

 SYN:链接建立的时候被置为1,以后始终被置0,即链接请求;【sync】

 FIN:finish,在链接断开时被设置为1,以后 始终被设置为0;


------muhuizz整理