①4位版本号,如今大规模使用的两个IP协议版本号为4(ip v4),6(ip v6)。
②4位首部长度。IP协议的报头也是像TCP报头那样可以通过选项变长的,报头长度也是像TCP报头那样为20~60个字节。
③8位服务类型(TOS)。8位服务类型(TOS)可以让IP协议切换形态。包括3位优先权字段(已经弃用)、4位TOS字段、和1位保留字段(必须置为0)。四个YOS位彼此之间是冲突的,只能有一位设为1表示IP协议不同的形态。不同的形态分别为:最小延时、最大吞吐量、最高可靠性、最小成本。但不同形态对IP协议的影响非常有限(比如形态设置为了最小延时但延时时间与原来并无太大差别),所以日常开发中这里的内容不太会涉及到。
④16位总长度。描述了IP数据包最长是多长。16位总长度表示最大只能达到64kb(即IP协议总的数据包长度太小),为了解决这个问题,IP协议自身支持大量数据的“拆包组包”功能,而不用像UDP那样需要程序员通过应用程序代码来实现大量数据的“拆包组包”。
⑤16位标识。
⑥3位标志。
⑦13位片偏移。
通过⑤⑥⑦这三个属性来支持IP协议的拆包组包,如果一个大的IP数据包需要拆成多个小的数据包,此时拆出来的这多个小的数据包的16位标识里的数值就是相同的,这保证了组包时数据的完整性。
3位标志第一位为保留位,第二位表示是否允许拆包,第三位表示是否是最后一个包(类似于单链表的结束标记)。
13位片偏移描述每个小的数据包(分片)的相对位置,这保证了组包时数据包能按正确的顺序拼接上。
⑧8位生存时间(TTL)。描述了IP数据包还能在网络中存活多久,TTL是以次数为单位,IP数据包被构造出来的时候,TTL会被设置成一个初始值(比如32、64、128……根据六度空间理论把TTL设置成这些数大概率是够用的),IP数据包在网络转发的过程中,每经过一个路由器转发TTL都会减1,如果IP数据包把TTL耗尽了都还没有找到目的IP地址,那么这个IP数据包就会被丢弃。这种机制的功能举例:丢弃掉目的IP不存在的数据包。
⑨8位协议。描述的是IP数据包的载荷是传输层的哪个协议,是UDP协议还是TCP协议还是其它传输层协议……
⑩16位首部校验和。16位首部校验和只校验IP协议的首部,不校验IP协议的载荷(因为传输层协议比如TCP、UDP等自身是有检验和的)。
⑩①32位源IP地址。
⑩②32位目的IP地址。
IP地址本质上是一个32位的整数,但为了方便人理解,把它写作了点分十进制的的形式,在机器的角度上,点分十进制表示的仍然是一个32位的整数。
一个IP地址可以分成两部分,即网络号(标识了一个局域网)和主机号(标识了局域网中的一个设备)。
比如假设局域网1里的路由器1IP地址为192.168.1.1、主机1IP地址为192.168.1.12、主机2IP地址为192.168.1.13、主机3IP地址为192.168.1.14。则在这个局域网中,网络号是192.168.1,192.168.1后面的1、12、13、14是主机号。
局域网2里的路由器2IP地址为192.168.0.1、主机1IP地址为192.168.0.12、主机2IP地址为192.168.0.13、主机3IP地址为192.168.0.14。则在这个局域网中,网络号是192.168.0,192.168.0后面的1、12、13、14是主机号。
局域网1和局域网2相连(路由器1和路由器2相连),这两个相邻的局域网的网络号不能相同(通过一个路由器连接的两个局域网叫相邻的局域网,比如局域网1和局域网2都通过路由器1相连)。
子网掩码:一个IP地址哪个部分是网络号哪个部分是主机号这不一定,子网掩码就是用来确定网络号的。
比如IPv4地址:192.168.100.177
子网掩码:255.255.255.0(即11111111.11111111.11111111.00000000)
子网掩码也是一个32位的整数,左侧都是1右侧都是0,被标记成1的部分就是网络号,左侧1的个数可以根据实际的网络环境灵活配置。
当下流行的网段划分是带有子网掩码的网段划分。
①如果一个IP地址的主机号全为0,则这个IP就表示网络号,代表一个局域网,具体的主机是不能分配这个IP的。比如:
192.168.100.0
255.255.255.0
②如果一个IP地址的主机号全为1,则这个IP是一个“广播IP地址”,具体的主机也是不能分配这个IP的。UDP自身天然能支持广播传输,是因为UDP的socket给这个广播IP地址发送了UDP数据报,此时局域网中的所有设备都能收到这个数据报。而TCP无法和这个广播IP地址建立连接。比如:
192.168.100.255
255.255.255.0
③如果一个IP以127开头,此时这个IP就是环回IP(loopback),操作系统提供了一个特殊的“虚拟网卡”关联到这个IP上。环回IP的用途:比如进行一些测试性的工作,比如测试时我们要把一台主机的数据传输给另一台主机当出现问题时我们无法知道是网络不通畅引起的问题还是代码引起的问题,环回IP能够排除网络不通的干扰,使我们更好地排查代码中的问题。
最常用的环回IP是127.0.0.1。
IP地址是一个32位的整数,2的32次方等于42亿9千万。IP地址是不能重复读的,实际上如今互联网中能上网的设备非常多,上网设备已经超过了42亿9千万这个数字。
那么如何解决IP地址不够用的问题呢?
让不需要上网的设备把IP地址让出来给需要上网的设备使用。这个方案提高了IP地址的利用率并没有增加IP地址的数目,治标不治本,这是一个过度方案,但这个方案目前仍然广泛存在。
即让一个IP地址代表一批设备。
把IP地址分成两大类:
①内网IP(局域网IP),如果一个IP地址是10.* 或者172.16.* ~172.31.* 或者192.168.* ,则这个IP地址就是内网IP地址。
在同一个内网中内网IP之间不能重复,在不同的内网中内网IP之间可以重复。
②外网IP(广域网IP),10.* 或者172.16.* ~172.31.* 或者192.168.* 之外的IP都是外网IP,外网IP不能重复。
NAT机制的工作流程:
假设本端的电脑发送数据,数据先到达运营商路由器,然后再到达广域网,最后到达服务器。
(1)本端的电脑构造一个IP数据包(假设源IP为192.168.0.200),
(2)这个IP数据包到达运营商路由器(运营商路由器支持NAT机制)后,运营商路由器将IP数据包的源IP192.168.0.200(内网IP)替换为外网IP123.139.168.15,此时IP数据包的源IP就从内网IP替换为了外网IP,
(3)然后这个IP数据包通过广域网发给服务器,在服务器看来这个IP数据包的源IP是刚才替换完的外网IP,
上诉是客户端发送请求给服务器的NAT机制,下面介绍服务器返回响应给客户端的NAT机制。
这里要讨论的问题是如果一个内网中有很多主机访问同一个网站服务器,此时服务器返回响应经过运营商路由器的时候,运营商路由器该如何区分这个响应到底是响应给哪个主机的呢?这是根据区分主机之间的端口号来进行实现的,端口号可以用来区分同一个主机里的不同进程,也可以用来区分不同主机里的不同进程(因为不同设备操作系统分配的端口号大概率是不同的)。
比如一个主机的IP数据包源IP为192.168.0.200,源端口为9000。另一个主机的IP数据包源IP为192.168.0.300,源端口为8000。这两个主机的源IP经过运营商路由器之后都替换成了外网IP123.139.168.15。
站在服务器的角度,这两个IP数据包虽然有同样的源IP,但这两个IP数据包之间的端口不一样,因此服务器返回给两个主机的响应也会带有不同的目的端口(即刚才的源端口)。服务器返回的两条响应,一条响应的目的端口是9000另一条响应的目的端口是8000。
两条响应通过广域网回到运营商路由器的时候,运营商路由器会将端口为9000的响应数据的源IP(外网IP)替换回内网IP192.168.0.200,将端口为8000的响应数据的源IP(外网IP)替换回内网IP192.168.0.300。
但这里还有一个问题,如果两个主机分配到的端口号是一样的那怎么办?
为了解决这个问题,两个主机的IP数据包从主机发送到运营商路由器时,如果运营商路由器发现这两个IP数据包的端口号一样,会把这两个相同的端口替换为不同的端口,接下来以下的流程就可以继续正常执行了。
NAT机制最大的优势是NAT机制是软件层面的方案,不需要升级硬件设备。
因为NAT这个机制,所以局域网内部的设备能主动访问外网的设备,而外网的设备无法主动访问局域网内部的设备(因为在不同局域网里内网IP可以重复)。NAT机制也保护了我们电脑的安全。
NAT机制同动态分配IP一样只是提高了IP地址的复用程度,并没有增加IP地址的数量,治标不治本,最终IP地址不够用的问题需要IPv6来解决。
IPv6使用16个字节来表示IP地址。4个字节能表示的数据个数是2^32。 16个字节能表示的数据个数是 2^32 * 2^32 * 2^32 * 2^32(这是一个很大的数字)。但IPv6在世界上的普及程度不高。
IP数据包转发的过程是一个“探索式”、“启发式”的过程,因为网络中的每个路由器只能知道自己和哪些设备相连,而无法知道网络路线的全貌。
一个IP数据报每次转发到一个路由器中时,路由器会根据IP数据报中的目的IP查路由表里的表项(路由表是路由器内部的数据结构,路演表里的内容可以由网管来手动配置也可以自动获取(涉及到一系列的路由表生成算法)),如果查到了就按路由表给定的网络接口进行转发;如果没查到就按照默认表项转发(路由表里有一个默认表项即下一跳地址)。
以太网协议:
数据链路层里一个常用的协议是以太网协议。以太网协议横跨数据链路层、物理层,比如以太网协议规定网线水晶头的标准。
以太网协议是跟网线(有线)通信方式有关的协议。无线通信方式有wifi、移动流量(4G5G)。
以太网数据帧由帧头、载荷(IP数据报)、帧尾构成,帧尾是校验和。
①目的地址。
②源地址。
目的地址和源地址的大小为6个字节。以太网数据帧里的目的地址和源地址是mac地址(物理地址),mac地址是网络中的另一套地址体系,mac地址的定位和IP地址有一定的冲突/重合。mac地址由6个字节组成,能表示数据的个数比IP地址大很多,所以mac地址目前还是够用的,每个设备目前都有唯一的mac地址。
mac地址是网卡出厂的时候就写死的一般不能对mac地址进行修改。
mac地址可以作为一台网络设备的身份标识,可以根据mac地址进行定位,也可以通过mac地址来让软件和机器进行绑定(软件和机器进行绑定后,软件就只能安装在这台机器上,换一台机器就要重新买一份软件)。
mac地址通常是用十六进制来表示,两个十六进制数字表示一个字节,字节和字节之间通常使用-或者:来分割。比如00-E0-4C-8D-46-E6。
网络层关注的是整体的网络路径,应该走哪条网络路径。
数据链路层关注的是网络路径中相邻节点之间如何转发。
所以数据报的源IP和目的IP在整个通信过程中立足于全局不会改变(这里不考虑NAT机制);而数据报每次到达一个节点要往下一个节点转发的时候,源mac和目的mac都会随之改变。
③类型。类型描述的是以太网数据帧的载荷数据的类型。
载荷数据的类型:
(1)IP数据包。以太网数据帧规定其载荷中的IP数据包的长度为46~1500个字节,即IP数据包最大长度不能超过1500个字节(即数据链路层的数据报能携带的最大载荷长度MTU)。1500个字节要小于IP协议的最大报文长度64kb,所有IP数据报的分包组包大概率是因为超过MTU引起的而不是因为超过IP数据报最大报文长度64kb引起的。
数据链路层中不同协议的MTU是不同的,这和物理层的传输介质有关。
(2)ARP请求/应答。
(3)RARP请求/应答。
(2)和(3)传输的不是业务数据而是辅助转发的数据。交换机收到以太网数据帧的时候需要进行转发,这个转发过程需要根据MAC地址查转发表(交换机内部有一个数据结构“转发表”,转发表是一个像哈希这样的映射(转发表不一定是软件实现的也有可能由硬件实现))判断出数据需要走哪个网络接口来进行转发(这里的网络接口是物理上能够插网线的网口,路由器说的要走哪个网口是一个抽象的概念,最终还是要在数据链路层才能决定走哪个物理网口)。转发表的构造通过ARP协议来生成。