今天我们来学ip协议!
如果我们想要两台主机之间能够通信必须知道双方的ip地址才能进行标识对方然后进行通信!
首先是4位首部长度,与tcp同理*4才是报头的真实大小!(即20-60)(最低开始读20,保证除选项外的报头肯定读上去了)
4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4
8 位服务类型 (Type Of Service): 3 位优先权字段 ( 已经弃用 ), 4 位 TOS 字段 , 和 1 位保留字段 ( 必须置为 0). 4 位 TOS分别表示 : 最小延时 , 最大吞吐量 , 最高可靠性 , 最小成本 . 这四者相互冲突 , 只能选择一个 . 对于 ssh/telnet这样的应用程序 , 最小延时比较重要 ; 对于 ftp 这样的程序 , 最大吞吐量比较重要 .
16 位总长度 (total length): IP 数据报整体占多少个字节
8 位协议 : 表示上层协议的类型(标识要把数据交到上层的哪一个协议里面去)
32 位源地址和 32 位目标地址 : 表示发送端和接收端 .
上面的我们先介绍这一部分然后我们先看看
网段划分 ( 重要 )
IP 地址分为两个部分 , 网络号和主机号
网络号 : 保证相互连接的两个网段具有不同的标识 ;
主机号 : 同一网段内 , 主机之间具有相同的网络号 , 但是必须有不同的主机号 ;
不同的子网其实就是把网络号相同的主机放到一起 .
如果在子网中新增一台主机, 则这台主机的网络号和这个子网的网络号一致 , 但是主机号必须不能和子网
中的其他主机重复 . 通过合理设置主机号和网络号, 就可以保证在相互连接的网络中 , 每台主机的 IP 地址都不相同 . 那么问题来了, 手动管理子网内的 IP, 是一个相当麻烦的事情 .
有一种技术叫做 DHCP, 能够自动的给子网内新增主机节点分配 IP 地址 , 避免了手动管理 IP 的不便 .
一般的路由器都带有 DHCP 功能 . 因此路由器也可以看做一个 DHCP 服务器 .
我们在这里也稍微提一下路由器的作用
1.路由器本质也是特定一个子网的主机,也要配置ip地址
2.路由器一定至少要连接2个子网,路由器也就相当于同时在两个子网
3.路由器一般是一个子网中的第一台设备,一般他的IP地址都是:网络号.1
4.路由器功能,ip报文的转发,不仅仅如此~,构建子网(局域网)
过去曾经提出一种划分网络号和主机号的方案 , 把所有 IP 地址分为五类 , 如下图所示
随着 Internet 的飞速发展 , 这种划分方案的局限性很快显现出来 , 大多数组织都申请 B 类网络地址 , 导致 B 类地址很快就
分配完了 , 而 A 类却浪费了大量地址 ; 例如, 申请了一个 B 类地址 , 理论上一个子网内能允许 6 万 5 千多个主机 . A 类地址的子网内的主机数更多 .
然而实际网络架设中 , 不会存在一个子网内有这么多的情况 . 因此大量的 IP 地址都被浪费掉了 .
针对这种情况提出了新的划分方案 , 称为 CIDR(Classless Interdomain Routing):
引入一个额外的子网掩码 (subnet mask) 来区分网络号和主机号 ;
子网掩码也是一个 32 位的正整数 . 通常用一串 "0" 来结尾 ;
将 IP 地址和子网掩码进行 " 按位与 " 操作 , 得到的结果就是网络号 ;
网络号和主机号的划分与这个 IP 地址是 A 类、 B 类还是 C 类无关 ;
可见 ,IP 地址与子网掩码做与运算可以得到网络号 , 主机号从全 0 到全 1 就是子网的地址范围 ;
IP 地址和子网掩码还有一种更简洁的表示方法 , 例如 140.252.20.68/24, 表示 IP 地址为 140.252.20.68, 子网掩码的高 24位是 1, 也就是 255.255.255.0
也就是用子网掩码的1的部分为网络号,0为主机号,1和0就划分了网络号和主机号的部分!
这里注意一下不存在主机号为0或者全1的主机(要用作特殊用途,比如广播)
将 IP 地址中的主机地址全部设为 0, 就成为了网络号 , 代表这个局域网 ;
将 IP 地址中的主机地址全部设为 1, 就成为了广播地址 , 用于给同一个链路中相互连接的所有主机发送数 据包;
127.* 的 IP 地址用于本机环回 (loop back) 测试 , 通常是 127.0.0.1
IP 地址的数量限制
我们知道 , IP 地址 (IPv4) 是一个 4 字节 32 位的正整数 . 那么一共只有 2 的 32 次方 个 IP 地址 , 大概是 43 亿左右 . 而 TCP/IP 协议规定, 每个主机都需要有一个 IP 地址 . 这意味着, 一共只有 43 亿台主机能接入网络么 ?
实际上 , 由于一些特殊的 IP 地址的存在 , 数量远不足 43 亿 ; 另外 IP 地址并非是按照主机台数来配置的 , 而是每一个网卡 都需要配置一个或多个IP 地址 .
CIDR 在一定程度上缓解了 IP 地址不够用的问题 ( 提高了利用率 , 减少了浪费 , 但是 IP 地址的绝对上限并没有增加 ), 仍然 不是很够用. 这时候有三种方式来解决 :
动态分配 IP 地址 : 只给接入网络的设备分配 IP 地址 . 因此同一个 MAC 地址的设备 , 每次接入互联网中 , 得到 的IP 地址不一定是相同的 ; NAT技术 ( 后面会重点介绍 );
IPv6: IPv6 并不是 IPv4 的简单升级版 . 这是互不相干的两个协议 , 彼此并不兼容 ; IPv6 用 16 字节 128 位来表 示一个IP 地址 ; 但是目前 IPv6 还没有普及 ;
私有 IP 地址和公网 IP 地址
如果一个组织内部组建局域网 ,IP 地址只用于局域网内的通信 , 而不直接连到 Internet 上 , 理论上 使用任意的 IP 地址都 可以, 但是 RFC 1918 规定了用于组建局域网的私有 IP 地址
10.*, 前 8 位是网络号 , 共 16,777,216 个地址
172.16. 到 172.31. , 前 12 位是网络号 , 共 1,048,576 个地址
192.168.*, 前 16 位是网络号 , 共 65,536 个地址
包含在这个范围中的 , 都称为私有 IP, 其余的则称为全局 IP( 或公网 IP);
一个路由器可以配置两个 IP 地址 , 一个是 WAN 口 IP, 一个是 LAN 口 IP( 子网 IP).
路由器 LAN 口连接的主机 , 都从属于当前这个路由器的子网中 .
不同的路由器 , 子网 IP 其实都是一样的 ( 通常都是 192.168.1.1). 子网内的主机 IP 地址不能重复 . 但是子网之 间的IP 地址就可以重复了 .
每一个家用路由器 , 其实又作为运营商路由器的子网中的一个节点 . 这样的运营商路由器可能会有很多级 , 最外层的运营商路由器, WAN 口 IP 就是一个公网 IP 了 .
子网内的主机需要和外网进行通信时 , 路由器将 IP 首部中的 IP 地址进行替换 ( 替换成 WAN 口 IP), 这样逐级 替换, 最终数据包中的 IP 地址成为一个公网 IP. 这种技术称为 NAT(Network Address Translation ,网络地 址转换).
如果希望我们自己实现的服务器程序 , 能够在公网上被访问到 , 就需要把程序部署在一台具有外网 IP 的服 务器上. 这样的服务器可以在阿里云 / 腾讯云上进行购买
简而言之,就是套娃!公网ip有限,所以真正能拿到公网ip的只能是少数(一般是运营商的路由器等)。然后在一个公网ip内部再组建私网,这样就扩充ip数量,缓解了ip不足的问题!然后再进行转发的时候运营商路由器就对发送ip进行层层替换,这样对方再发回信息的时候就能重新抵达运营商路由器,至于如何从运营商路由器返回主机我们后面再学习!(NAT部分)
然后我们就可以继续将一下ip协议的报头了!
3 位标志字段 : 第一位保留 ( 保留的意思是现在不用 , 但是还没想好说不定以后要用到 ). 第二位置为 1 表示禁 止分片, 这时候如果报文长度超过 MTU, IP 模块就会丢弃报文 . 第三位表示 " 更多分片 ", 如果分片了的话 , 最后一个分片置为1, 其他是 0. 类似于一个结束标记 .
13 位分片偏移 (framegament offffset): 是分片相对于原始 IP 报文开始处的偏移 . 其实就是在表示当前分片 在原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的 . 因此 , 除了最后一个报文之外 , 其他报 文的长度必须是8 的整数倍 ( 否则报文就不连续了 ).
这样只要被分片了,那么只要片偏移不等于0或者更多分片等于1.就可以判断有没有分片和是否完整收到报文了!(如果报头,收到后面的自然知道报头有缺失,可以进行补发,如果中间有丢失显然会有偏移量没有连续,同理,如果报尾丢失,则会没有更多分片为0的报文(即片尾)同理可以查出来)!
然后我们就可以开始学习数据链路层了!
首先我们学习mac帧的报头!
源地址和目的地址是指网卡的硬件地址 ( 也叫 MAC 地址 ), 长度是 48 位 , 是在网卡出厂时固化的 ;
帧协议类型字段有三种值 , 分别对应 IP 、 ARP 、 RARP;
帧末尾是 CRC 校验码
mac帧在局域网中使用!每进入一个新的局域网传输都会重新封装mac帧!
一旦 UDP 携带的数据超过 1472(1500 - 20(IP 首部 ) - 8(UDP 首部 )), 那么就会在网络层分成多个 IP 数据报 . 这多个IP 数据报有任意一个丢失 , 都会引起接收端网络层重组失败 . 那么这就意味着 , 如果 UDP 数据报在 网络层被分片, 整个数据被丢失的概率就大大增加了
认识 MTU
MTU 相当于发快递时对包裹尺寸的限制 . 这个限制是不同的数据链路对应的物理层 , 产生的限制 .
以太网帧中的数据长度规定最小 46 字节 , 最大 1500 字节 ,ARP 数据包的长度不够 46 字节 , 要在后面补填充 位;
最大值 1500 称为以太网的最大传输单元 (MTU), 不同的网络类型有不同的 MTU;
如果一个数据包从以太网路由到拨号链路上 , 数据包长度大于拨号链路的 MTU 了 , 则需要对数据包进行分 片(fragmentation); 不同的数据链路层标准的MTU 是不同的 ;
MTU 对 IP 协议的影响
由于数据链路层 MTU 的限制 , 对于较大的 IP 数据包要进行分包 .
将较大的 IP 包分成多个小包 , 并给每个小包打上标签 ;
每个小包 IP 协议头的 16 位标识 (id) 都是相同的 ;
每个小包的 IP 协议头的 3 位标志字段中 , 第 2 位置为 0, 表示允许分片 , 第 3 位来表示结束标记 ( 当前是否是最 后一个小包, 是的话置为 1, 否则置为 0);
到达对端时再将这些小包 , 会按顺序重组 , 拼装到一起返回给传输层 ;
一旦这些小包中任意一个小包丢失 , 接收端的重组就会失败 . 但是 IP 层不会负责重新传输数据 ;(也就是前面的分片)
但是我们一般tcp都会优先分包,这样哪怕丢失了也只用重发一个小包!如果发送一个很大的包让数据链路层去分片,一个分片丢了整个大包都要重发,会导致效率降低!
ARP 协议的作用
ARP 协议建立了主机 IP 地址 和 MAC 地址 的映射关系 .
在网络通讯时 , 源主机的应用程序知道目的主机的 IP 地址和端口号 , 却不知道目的主机的硬件地址 ;
数据包首先是被网卡接收到再去处理上层协议的 , 如果接收到的数据包的硬件地址与本机不符 , 则直接丢 弃;
因此在通讯前必须获得目的主机的硬件地址 ;
ARP 协议的工作流程
源主机发出 ARP 请求 , 询问 "IP 地址是 192.168.0.1 的主机的硬件地址是多少 ", 并将这个请求广播到本地网 段( 以太网帧首部的硬件地址填 FF:FF:FF:FF:FF:FF 表示广播 );
目的主机接收到广播的 ARP 请求 , 发现其中的 IP 地址与本机相符 , 则发送一个 ARP 应答数据包给源主机 , 将自 己的硬件地址填写在应答包中;
每台主机都维护一个 ARP 缓存表 , 可以用 arp -a 命令查看。缓存表中的表项有过期时间 ( 一般为 20 分钟 ), 如 果20 分钟内没有再次使用某个表项 , 则该表项失效 , 下次还要发 ARP 请求来获得目的主机的硬件地址
注意到源 MAC 地址、目的 MAC 地址在以太网首部和 ARP 请求中各出现一次 , 对于链路层为以太网的情况 是多余的, 但如果链路层是其它类型的网络则有可能是必要的。
硬件类型指链路层网络类型 ,1 为以太网 ;
协议类型指要转换的地址类型 ,0x0800 为 IP 地址 ;
硬件地址长度对于以太网地址为 6 字节 ;
协议地址长度对于和 IP 地址为 4 字节 ;
op 字段为 1 表示 ARP 请求 ,op 字段为 2 表示 ARP 应答。
NAT 技术
NAT 技术背景
之前我们讨论了 , IPv4 协议中 , IP 地址数量不充足的问题
NAT 技术当前解决 IP 地址不够用的主要手段 , 是路由器的一个重要功能 ;
NAT 能够将私有 IP 对外通信时转为全局 IP. 也就是就是一种将私有 IP 和全局 IP 相互转化的技术方法 :
很多学校 , 家庭 , 公司内部采用每个终端设置私有 IP, 而在路由器或必要的服务器上设置全局 IP;
全局 IP 要求唯一 , 但是私有 IP 不需要 ; 在不同的局域网中出现相同的私有 IP 是完全不影响的 ;
NAT IP 转换过程
NAT 路由器将源地址从 10.0.0.10 替换成全局的 IP 202.244.174.37;
NAT 路由器收到外部的数据时 , 又会把目标 IP 从 202.244.174.37 替换回 10.0.0.10;
在 NAT 路由器内部 , 有一张自动生成的 , 用于地址转换的表 ;
当 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系 ;
NAPT
那么问题来了 , 如果局域网内 , 有多个主机都访问同一个外网服务器 , 那么对于服务器返回的数据中 , 目的 IP 都是相同 的. 那么 NAT 路由器如何判定将这个数据包转发给哪个局域网的主机 ?
这时候 NAPT 来解决这个问题了 . 使用 IP+port 来建立这个关联关系
这种关联关系也是由 NAT 路由器自动维护的 . 例如在 TCP 的情况下 , 建立连接时 , 就会生成这个表项 ; 在断开连接后 , 就 会删除这个表项
也即局域网内端口不会重复,而通过一个公网下面就可以建立一个庞大的私网,数据来往都通过这一个公网出入!这样就相对于增加了ip地址(复用)!然后为了保证双方能确认彼此,每一次在公网除都会根据转换表将公网的地址转化内网的地址(相对于一个签证,在不同区域内标识身份一样)就可以实现双方数据的通信了!
NAT 技术的缺陷
由于 NAT 依赖这个转换表 , 所以有诸多限
无法从 NAT 外部向内部服务器建立连接 ;
装换表的生成和销毁都需要额外开销 ;
通信过程中一旦 NAT 设备异常 , 即使存在热备 , 所有的 TCP 连接也都会断开 ;
NAT 和代理服务器
路由器往往都具备 NAT 设备的功能 , 通过 NAT 设备进行中转 , 完成子网设备和其他子网设备的通信过程 .
代理服务器看起来和 NAT 设备有一点像 . 客户端像代理服务器发送请求 , 代理服务器将请求转发给真正要请求的服务
器 ; 服务器返回结果后 , 代理服务器又把结果回传给客户端 .
那么 NAT 和代理服务器的区别有哪些呢 ?
从应用上讲 , NAT 设备是网络基础设备之一 , 解决的是 IP 不足的问题 . 代理服务器则是更贴近具体应用 , 比 如通过代理服务器进行翻墙, 另外像迅游这样的加速器 , 也是使用代理服务器 .
从底层实现上讲 , NAT 是工作在网络层 , 直接对 IP 地址进行替换 . 代理服务器往往工作在应用层 .
从使用范围上讲 , NAT 一般在局域网的出口部署 , 代理服务器可以在局域网做 , 也可以在广域网做 , 也可以 跨网. 从部署位置上看, NAT 一般集成在防火墙 , 路由器等硬件设备上 , 代理服务器则是一个软件程序 , 需要部署 在服务器上.
代理服务器是一种应用比较广的技术 .
翻墙 : 广域网中的代理 .
负载均衡 : 局域网中的代理 .
代理服务器又分为正向代理和反向代理
NAT 和代理服务器
路由器往往都具备 NAT 设备的功能 , 通过 NAT 设备进行中转 , 完成子网设备和其他子网设备的通信过程 .
代理服务器看起来和 NAT 设备有一点像 . 客户端像代理服务器发送请求 , 代理服务器将请求转发给真正要请求的服务 器; 服务器返回结果后 , 代理服务器又把结果回传给客户端 .
那么 NAT 和代理服务器的区别有哪些呢 ?
从应用上讲 , NAT 设备是网络基础设备之一 , 解决的是 IP 不足的问题 . 代理服务器则是更贴近具体应用 , 比 如通过代理服务器进行翻墙, 另外像迅游这样的加速器 , 也是使用代理服务器 .
从底层实现上讲 , NAT 是工作在网络层 , 直接对 IP 地址进行替换 . 代理服务器往往工作在应用层 .
从使用范围上讲 , NAT 一般在局域网的出口部署 , 代理服务器可以在局域网做 , 也可以在广域网做 , 也可以 跨网.
从部署位置上看 , NAT 一般集成在防火墙 , 路由器等硬件设备上 , 代理服务器则是一个软件程序 , 需要部署 在服务器上.
代理服务器是一种应用比较广的技术 .
翻墙 : 广域网中的代理 .
负载均衡 : 局域网中的代理 .
代理服务器又分为正向代理和反向代理 .
代购例子
花王尿不湿是一个很经典的尿不湿品牌 , 产自日本 .
我自己去日本买尿不湿比较不方便 , 但是可以让我在日本工作的表姐去超市买了快递给我 . 此时超市看到的买家是我表
姐 , 我的表姐就是 " 正向代理 ";
后来找我表姐买尿不湿的人太多了 , 我表姐觉得天天去超市太麻烦 , 干脆去超市买了一大批尿不湿屯在家里 , 如果有人 来找她代购, 就直接把屯在家里的货发出去 , 而不必再去超市 . 此时我表姐就是
" 反向代理
正向代理用于请求的转发 ( 例如借助代理绕过反爬虫 ).
反向代理往往作为一个缓存 .
然后我们最后再介绍一些 其他重要协议或技术 !
DNS(Domain Name System)
DNS 是一整套从域名映射到 IP 的系统
DNS 背景
TCP/IP 中使用 IP 地址和端口号来确定网络上的一台主机的一个程序 . 但是 IP 地址不方便记忆 .
于是人们发明了一种叫主机名的东西 , 是一个字符串 , 并且使用 hosts 文件来描述主机名和 IP 地址的关系 . 最初, 通过互连网信息中心 (SRI-NIC) 来管理这个 hosts 文件的 .
如果一个新计算机要接入网络 , 或者某个计算机 IP 变更 , 都需要到信息中心申请变更 hosts 文件 .
其他计算机也需要定期下载更新新版本的 hosts 文件才能正确上网 .
这样就太麻烦了 , 于是产生了 DNS 系统 .
一个组织的系统管理机构 , 维护系统内的每个主机的 IP 和主机名的对应关系 .
如果新计算机接入网络 , 将这个信息注册到数据库中 ;
用户输入域名的时候 , 会自动查询 DNS 服务器 , 由 DNS 服务器检索数据库 , 得到对应的 IP 地址 .
至今 , 我们的计算机上仍然保留了 hosts 文件 . 在域名解析的过程中仍然会优先查找 hosts 文件的内容 .
域名简介
主域名是用来识别主机名称和主机所属的组织机构的一种分层结构的名称 .
域名使用 . 连接
com: 一级域名 . 表示这是一个企业域名 . 同级的还有 "net"( 网络提供商 ), "org"( 非盈利组织 ) 等 .
baidu: 二级域名 , 公司名 .
www: 只是一种习惯用法 . 之前人们在使用域名时 , 往往命名成类似于 ftp.xxx.xxx/ www.xxx.xxx 这样的格 式, 来表示主机支持的协议
ICMP 协议
ICMP 协议是一个 网络层协议
一个新搭建好的网络 , 往往需要先进行一个简单的测试 , 来验证网络是否畅通 ; 但是 IP 协议并不提供可靠传输 . 如果丢 包了, IP 协议并不能通知传输层是否丢包以及丢包的原因 .
ICMP 功能
ICMP 正是提供这种功能的协议 ; ICMP 主要功能包括 :
确认 IP 包是否成功到达目标地址 .
通知在发送过程中 IP 包被丢弃的原因 .
ICMP 也是基于 IP 协议工作的 . 但是它并不是传输层的功能 , 因此人们仍然把它归结为网络层协议 ;
ICMP 只能搭配 IPv4 使用 . 如果是 IPv6 的情况下 , 需要是用 ICMPv6;
比如ping命令就是倚靠ICMP协议的!
不多讲!
ping 命令
注意 , 此处 ping 的是域名 , 而不是 url! 一个域名可以通过 DNS 解析成 IP 地址 .
ping 命令不光能验证网络的连通性 , 同时也会统计响应时间和 TTL(IP 包中的 Time To Live, 生存周期 ). ping命令会先发送一个 ICMP Echo Request 给对端 ;
对端接收到之后 , 会返回一个 ICMP Echo Reply;
traceroute 命令
也是基于 ICMP 协议实现 , 能够打印出可执行程序主机 , 一直到目标主机之前经历多少路由器 .
至此ip协议和数据链路层到此便告一段落!我们下节再见!