断网了还能 ping 通 127.0.0.1 吗?——CS-Base《图解网络》回环地址、localhost 与 0.0.0.0 深度解析
文档教程知识库【免费下载链接】CS-Base图解计算机网络、操作系统、计算机组成、数据库共 1000 张图 50 万字破除晦涩难懂的计算机基础知识让天下没有难懂的八股文 在线阅读https://xiaolincoding.com项目地址https://gitcode.com/GitHub_Trending/cs/CS-Base点击查看免费下载导读本文是 CS-Base《图解网络》IP 篇的核心实战之一network/4_ip/ping_lo.md从拔掉网线后 ping 127.0.0.1 依然通这个经典现象出发完整拆解回环地址的本质、ping 与普通 TCP 发包的底层差异、数据在本机假网卡上的收发路径以及 127.0.0.1、localhost、0.0.0.0 三者到底有什么区别。读完你将掌握为什么断网不影响回环通信、如何用抓包验证本机 IP 与回环地址的等效性以及服务器监听 0.0.0.0 的真实含义并能在面试八股与日常排障中直接复用这套分析思路。实验开场拔掉网线ping 127.0.0.1先做一个最直接的实验把网线拔掉、彻底断网然后在终端执行$ ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq0 ttl64 time0.080 ms 64 bytes from 127.0.0.1: icmp_seq1 ttl64 time0.093 ms 64 bytes from 127.0.0.1: icmp_seq2 ttl64 time0.074 ms 64 bytes from 127.0.0.1: icmp_seq3 ttl64 time0.079 ms 64 bytes from 127.0.0.1: icmp_seq4 ttl64 time0.079 ms ^C --- 127.0.0.1 ping statistics --- 5 packets transmitted, 5 packets received, 0.0% packet loss round-trip min/avg/max/stddev 0.074/0.081/0.093/0.006 ms结论很明确断网状态下ping 127.0.0.1依然能通5 个包全部收到、零丢包RTT 也只有零点几毫秒。但这不代表不用交网费就能上网。答案的关键在于回环地址loopback address的通信路径根本不经过真网卡数据包在本机内部转了个圈就回来了。下面逐层拆解背后的原理。什么是 127.0.0.1人为规定的回环地址IPv4 地址的位宽与书写方式127.0.0.1是一个IPv4 地址。IPv4 地址由 32 位正整数组成4 个字节人类为了便于记忆采用点分十进制表示32 位每 8 位一组、共分 4 组组间用.隔开每组再转成十进制。关于 IPv4 地址分类A/B/C/D/E、子网划分、CIDR 等完整背景见同目录的 IP 基础知识全家桶。127 网段都是回环地址以 127 开头的地址都属于回环地址是 IPv4 的特殊地址段。这是人为规定不需要问为什么。而127.0.0.1只是众多回环地址中的一个之所以默认是127.0.0.1而不是127.0.0.2是因为操作系统源码里就是这么定义的同样没什么道理。Linux 内核头文件中的定义如下/* Address to loopback in software to local host. */ #define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */0x7f000001正是127.0.0.1的十六进制形态0x7f 1270x00 00x00 00x01 1。IPv4 地址枯竭与 IPv6 的诞生IPv4 地址是 32 位的2 的 32 次方约40 多亿而地球人口早已超过 76 亿加上每台设备往往不止一块网卡IPv4 地址实际上早已被分配完毕这也是必须引入 NAT、CIDR 等缓解技术的原因详见 IP 基础知识全家桶 中的 NAT 与无分类地址小节。于是有了 IPv6地址长度128 位2 的 128 次方约等于 10 的 38 次方——地球沙子的数量约 10 的 23 次方IPv6 的地址量可以认为用不完。两种地址的书写差异IPv432 位以 8 位为一组共 4 组用.隔开点分十进制IPv6128 位以 16 位为一组共 8 组用:隔开如果某段全是 0可以把连续的 0 省略用::表示但一个 IPv6 地址中只允许出现一次::。IPv6 下的回环地址::1在 IPv4 中回环地址是127.0.0.1在 IPv6 中则表示为::1——中间省略了连续的多组 0最后一位是 1。之所以不是 7 个冒号而是 2 个冒号::正是上面说的一个 IPv6 地址中只允许出现一次两个连续的冒号的规则。对应的 ping 命令也要变化IPv4 下用ping 127.0.0.1IPv6 下用ping6 ::1。佐证在 IP 基础知识全家桶 的环回地址是不会流向网络一节中明确写到计算机使用特殊的 IP 地址127.0.0.1作为环回地址与之具有相同意义的还有localhost主机名使用这个 IP 或主机名时数据包不会流向网络。什么是 ping应用层命令 网络层 ICMPping是应用层命令它和游戏、聊天软件处于同一层。区别在于聊天软件功能复杂收发消息、点赞等而 ping 功能很简单——尝试向目标机器发送一个很小的消息判断目的机器是否可达也就是判断网络是否连通。ping 的底层使用的是网络层的ICMP 协议Internet Control Message Protocol互联网控制报文协议。虽然 ICMP 和 IP 都属于网络层协议但ICMP 报文实际上是利用 IP 协议进行传输的——ICMP 报文被封装在 IP 数据包里IP 首部中协议号字段为 1 即表示携带的是 ICMP 报文。ICMP 报文按类型字段分为两大类完整讲解见 ping 的工作原理查询报文类型用于诊断如回送请求Echo Request类型 8与回送应答Echo Reply类型 0——正是 ping 使用的消息相比原生 ICMP还多了标识符用于区分是哪个应用程序发的包常取进程 PID和序号从 0 开始每次发送加 1用于确认是否丢包并在选项数据中存放发送时间用于计算往返时间 RTT差错报文类型用于通知出错原因如目标不可达类型 3代码 0/1/2/3/4 分别表示网络不可达、主机不可达、协议不可达、端口不可达、需分片但设置了不分片位、原点抑制类型 4、重定向类型 5、超时类型 11对应 TTL 递减为 0。所以简单理解 ping 某个 IP就是往某个 IP 地址发个 ICMP 消息并等待回执。TCP 发数据和 ping 的区别同一套流程不同的 socket 类型一般情况下我们使用 TCP 进行网络数据传输。把它和 ping 横向对比能直观看出二者的共性与差异。共性都从应用层走向网卡以聊天软件用 TCP 发消息为例要发消息就得先知道往哪发。Linux 里万物皆文件发送目的地也是一个文件这里引出socket 概念。使用 socket 的第一步是创建它socket(AF_INET, SOCK_STREAM, 0);AF_INET表示将使用IPv4 里 host:port 的方式解析后面输入的网络地址SOCK_STREAM使用面向字节流的 TCP 协议工作在传输层。创建好 socket 后就可以把要传输的数据写到这个文件里。调用 socket 的sendto接口时进程会从用户态进入内核态最终调用到sock_sendmsg方法。随后数据依次进入传输层带上TCP 头→ 网络层带上IP 头→ 数据链路层带上MAC 头→ 进入网卡的发送队列 ring buffer顺着网卡发出。这一应用层 → 传输层 → 网络层 → 数据链路层 → 网卡的完整链路在 Linux 系统是如何收发网络包的 中有系统讲解。差异ping 使用原始套接字工作在网络层回到 ping整个过程与 TCP 发数据基本类似差异主要在于创建 socket 的参数socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)SOCK_RAW是原始套接字工作在网络层因此构建 ICMP网络层协议数据再合适不过IPPROTO_ICMP明确指定协议为 ICMP。ping 进入内核态后最后调用的同样是sock_sendmsg方法进入网络层后加上ICMP 头 IP 头数据链路层加上MAC 头也是顺着网卡发出。因此本质上ping 和普通应用发消息在程序流程上没太大差别。这也解释了为什么排查网络问题时第一反应总是你能 ping 通吗ping 相当于自己组了一个数据包让系统按其他软件发数据的路径往外发一遍能通就说明其他软件发数据也能通。完整的 ICMP 请求/应答报文交互细节见 ping 的工作原理。为什么断网了还能 ping 通 127.0.0.1本地假网卡的完整路径前面提到有网的情况下 ping 最后是通过真网卡把数据发送出去的。那么断网时网卡已经不工作了ping 回环地址却一切正常它的数据到底走的是哪条路网络层路由表决定走哪块网卡从应用层到传输层再到网络层这段路径跟 ping 外网时几乎一样。到了网络层系统会根据目的 IP 在路由表中查询对应的路由信息而路由信息中就包含选择哪块网卡发出消息当发现目标 IP 是外网 IP时会从真网卡发出当发现目标 IP 是回环地址时就会选择本地网卡loopback 接口。路由表按网络地址匹配目标、遵循最长匹配原则的机制在 IP 基础知识全家桶 的IP 地址与路由控制一节有详细说明。本地网卡没有 ring buffer 的假网卡本地网卡其实是个**假网卡**它不像真网卡那样有发送队列 ring buffer。它的工作方式是假网卡把数据推到一个叫input_pkt_queue的链表中——这个链表是所有网卡共享的上面挂着发给本机的各种消息消息进入链表后会触发一次软中断专门处理软中断的内核线程ksoftirqd收到软中断后立马从链表里取出消息然后顺着数据链路层、网络层等层层往上传递最后把数据交给应用程序。深度佐证在 什么是软中断 中可以看到软中断以内核线程方式执行每个 CPU 对应一个软中断内核线程名字通常是ksoftirqd/CPU 编号如 0 号 CPU 对应ksoftirqd/0网络接收对应的软中断类型是NET_RX可以通过/proc/softirqs查看各 CPU 的软中断累计次数用ps命令可以看到中括号内的内核线程 ksoftirqd。结论整条路径根本没出网络ping 回环地址以及通过 TCP 等各种协议发送数据到回环地址走的都是上面这条路径——从发到收全程没有经过真网卡。之所以 127.0.0.1 叫本地回环地址可以理解为消息发到这个地址上就不会出网络在本机打一个转就又回来了。所以断网依然能 ping 通 127.0.0.1。同时这也说明能 ping 通 127.0.0.1 只代表本机网络协议栈工作正常与是否缴纳网费、能否访问外网毫无关系。ping 回环地址和 ping 本机地址有什么区别抓包验证二者等价很多人有一个直觉ping 本机 IP真网卡的地址会从真网卡出去遇到第一个路由器再绕回来。这个说法对不对用ifconfig和抓包来验证。在 mac 上执行ifconfig$ ifconfig lo0: flags8049UP,LOOPBACK,RUNNING,MULTICAST mtu 16384 inet 127.0.0.1 netmask 0xff000000 ... en0: flags8863UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST mtu 1500 inet 192.168.31.6 netmask 0xffffff00 broadcast 192.168.31.255 ...lo0本地回环接口对应地址就是前面提到的127.0.0.1也就是回环地址en0本机第一块真网卡Linux 下通常叫 eth0对应 IP 地址192.168.31.6即本机 IP。接下来对两种 ping 分别抓包观察数据流经的接口ping 127.0.0.1相关网络数据走的都是lo0ping 192.168.31.6本机地址抓包结果与上面相同同样走的是lo0。也就是说只要走了本地回环接口数据都不会发送到网络中在本机网络协议栈里兜一圈就发回来了。结论非常干脆ping 回环地址和 ping 本机地址没有区别——本机 IP 的数据包同样会在即将出网卡前被路由选择逻辑拉回本地回环路径而非真的发送到物理网络中。127.0.0.1、localhost、0.0.0.0 有区别吗面试常客的完整辨析用 nginx 做实验时会发现访问127.0.0.1:80、localhost:80、0.0.0.0:80以及本机 IP 的 80 端口都能看到 nginx 欢迎页容易让人误以为这几个地址完全一样。但本质上是有区别的。localhost是域名不是 IPlocalhost不叫 IP它是一个域名形式和baidu.com一样。只不过操作系统默认会把localhost解析为127.0.0.1并且这个映射可以在/etc/hosts文件中修改。所以默认情况下使用localhost和使用127.0.0.1确实没区别——因为二者最终解析到同一个回环地址但只要改掉/etc/hosts里的映射localhost 的含义就会随之改变。0.0.0.0无效的目标地址却是万能的服务监听地址先看ping 0.0.0.0它会失败$ ping 0.0.0.0 PING 0.0.0.0 (0.0.0.0): 56 data bytes ping: sendto: No route to host ping: sendto: No route to host因为0.0.0.0在 IPv4 中表示的是无效的目标地址——没有任何主机以它作为自己的地址路由表里自然找不到去往它的路由。但它有另一个重要用途服务端监听。我们启动服务器时一般会listen一个 IP 和端口等待客户端连接/* Address to accept any incoming messages. */ #define INADDR_ANY ((unsigned long int) 0x00000000) /* 0.0.0.0 */如果此时listen的是0.0.0.0那么它表示本机上的所有 IPv4 地址。举个例子刚才提到的127.0.0.1和192.168.31.6都是本机的 IPv4 地址如果服务监听0.0.0.0那么用上面两个地址都能访问到这个服务器。反过来如果只 listen 了某个具体地址如 127.0.0.1那只有该地址能访问其他地址访问会被拒绝。佐证在 服务端没有 listen客户端发起连接建立会发生什么 的示例代码中服务端正是用server_addr.sin_addr.s_addr htonl(INADDR_ANY);绑定0.0.0.0实现对本机所有 IPv4 地址 端口的监听。而作为客户端connect时不能使用0.0.0.0必须指明要连接哪个具体的服务器 IP。总结三个必须记住的结论127.0.0.1是回环地址localhost是域名默认情况下解析结果等于127.0.0.1可通过/etc/hosts修改。ping 回环地址和 ping 本机地址是一样的都走 lo0 这个假网卡都会经过网络层和数据链路层等逻辑最后在快要出网卡前狠狠拐了个弯把数据插入共享链表input_pkt_queue触发软中断由内核线程ksoftirqd执行收数据的逻辑——压根就不出网络。所以断网了也能 ping 通回环地址。如果服务器listen的是0.0.0.0即INADDR_ANY那么用127.0.0.1和本机地址都可以访问到服务而0.0.0.0不能作为 ping 的目标也不能作为客户端 connect 的目标。面试遇到断网了还能 ping 通 127.0.0.1 吗127.0.0.1 和 localhost 有什么区别服务器为什么要监听 0.0.0.0这类问题时只要抓住一条主线即可答全回环通信全程在本机协议栈内完成不经过物理网卡——这正是断网可通、localhost 等价于 127.0.0.1、0.0.0.0 只是通配所有本机地址的根本原因。延伸阅读本仓库关联章节IP 基础知识全家桶IP 分类、CIDR、子网划分、环回地址不会流向网络、NAT 等完整背景ping 的工作原理ICMP 查询/差错报文类型、ping 与 traceroute 的完整收发流程什么是软中断ksoftirqd 内核线程、NET_RX 软中断、/proc/softirqs 排查方法Linux 系统是如何收发网络包的应用层到网卡的完整收发链路服务端没有 listen客户端发起连接建立会发生什么INADDR_ANY绑定与监听语义的代码示例《图解网络》目录与阅读指引查看本书完整章节结构赞分享文档教程知识库【免费下载链接】CS-Base图解计算机网络、操作系统、计算机组成、数据库共 1000 张图 50 万字破除晦涩难懂的计算机基础知识让天下没有难懂的八股文 在线阅读https://xiaolincoding.com项目地址https://gitcode.com/GitHub_Trending/cs/CS-Base点击查看免费下载相关推荐Raylib 跑通全路径源码构建 CMake 接入 5 个高频报错解法Raylib 跑通全路径源码构建 CMake 接入 5 个高频报错解法 raylib 编译报错里最高频的是 undefined reference t游戏开发图形学3D渲染CS-Base 图解网络键入网址到网页显示期间发生了什么——HTTP、DNS、TCP、IP、MAC 全链路拆解CS Base 图解网络键入网址到网页显示期间发生了什么——HTTP、DNS、TCP、IP、MAC 全链路拆解 本篇技术指南以 CS Base图解计算机文档教程知识库Homebrew 包管理器指南一条命令装好软件Brewfile 一键还原整台机器Homebrew 包管理器指南一条命令装好软件Brewfile 一键还原整台机器 Homebrew 包管理器把装软件、管版本、跑服务这几件琐事全接走了命令CLI包管理器上一篇免费网页版LRC歌词制作工具歌词滚动姬完整使用指南下一篇免费网页版LRC歌词制作工具3分钟学会制作精准歌词创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →