共计 5135 个字符,预计需要花费 13 分钟才能阅读完成。
首发于集体公众号:golang 小白成长记
原文地址:硬核图解!断网了,还能 ping 通 127.0.0.1 吗?为什么?
你 女神爱不爱你,你问她,她可能不会通知你。
但 网通不通,你 ping
一下就晓得了。
可能看到题目,你就晓得答案了,然而你理解背地的起因吗?那如果把 127.0.0.1
换成 0.0.0.0
或 localhost
会怎么样呢?你晓得这几个 IP
有什么区别吗?
以前面试的时候就遇到过这个问题,大家看个动图理解下面试官和我过后的场景,求过后小白的心里暗影面积。
话不多说,咱们间接开车。
拔掉网线,断网。
而后在控制台输出 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_seq=0 ttl=64 time=0.080 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.093 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.079 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.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
是 能 ping 通的。
其实这篇文章看到这里,题目前半个问题曾经被答复了。然而咱们能够再想深一点。
为什么断网了还能 ping
通 127.0.0.1
呢?
这能阐明你不必交网费就能上网吗?
不能。
首先咱们须要进入根底科普环节。
不懂的同学看了就懂了,懂的看了就当查漏补缺吧。
什么是 127.0.0.1
首先,这是个 IPV4
地址。
IPV4
地址有 32
位,一个字节有 8
位,共 4
个字节。
其中127 结尾的都属于回环地址,也是 IPV4
的非凡地址,没什么情理,就是人为规定的。
而 127.0.0.1
是泛滥 回环地址中的一个。之所以不是 127.0.0.2
,而是 127.0.0.1
,是因为源码里就是这么定义的,也没什么情理。
/* Address to loopback in software to local host. */
#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */
IPv4
的地址是 32
位的,2 的 32 次方,大略是 40+ 亿
。地球光人口就 76 亿了,40 亿 IP 这点量, 塞牙缝都不够 ,实际上IP 也的确用完 了。
所以就有了IPV6
,IPv6
的地址是 128
位的,大略是 2 的 128 次方≈10 的 38 次方。据说地球的沙子数量大略是 10 的 23 次方,所以 IPV6 的 IP 能够认为用不完。
IPV4 以 8 位一组,每组之间用 . 号隔开。
IPV6 就以 16 位为一组,每组之间用 : 号隔开。如果全是 0,那么能够省略不写。
在 IPV4 下的回环地址是 127.0.0.1
,在 IPV6
下,表白为 ::1
。两头把 间断的 0 给省略了,之所以不是 7 个 冒号,而是 2 个冒号:,是因为一个 IPV6 地址中 只容许呈现⼀次两个间断的冒号。
多说一句:在 IPV4 下用的是 ping 127.0.0.1 命令。在 IPV6 下用的是 ping6 ::1 命令。
什么是 ping
ping 是应用层命令,能够了解为它跟游戏或者聊天软件属于同一层。只不过聊天软件能够收发音讯,还能点个赞什么的,有很多简单的性能。而 ping 作为一个小软件,它的性能比较简单,就是 尝试 发送一个小小的音讯到指标机器上,判断目标机器是否 可达,其实也就是判断指标机器网络是否能连通。
ping 利用的底层,用的是网络层的ICMP 协定。
尽管 ICMP 协定和 IP 协定 都属于网络层协定,但其实ICMP 也是利用了 IP 协定进行音讯的传输。
所以,大家在这里齐全能够简略的了解为 ping 某个 IP 就是往某个 IP 地址发个音讯。
TCP 发数据和 ping 的区别
个别状况下,咱们会应用 TCP 进行网络数据传输,那么咱们能够看下它和 ping 的区别。
ping 和其余应用层软件都属于 应用层。
那么咱们横向比照一下,比方说聊天软件,如果用的是 TCP 的形式去发送音讯。
为了发送音讯,那就得先晓得往哪发。linux 里万物皆文件,那你要发消息的目的地,也是个文件,这里就引出了 socket 的概念。
要应用 socket
, 那么首先须要创立它。
在 TCP 传输中创立的形式是 socket(AF_INET, SOCK_STREAM, 0);
,其中 AF_INET
示意将应用 IPV4 里 host:port 的形式去解析待会你输出的网络地址。SOCK_STREAM
是指应用面向字节流的 TCP 协定,工作在传输层。
创立好了 socket
之后,就能够欢快的把要传输的数据写到这个文件里。调用 socket 的 sendto
接口的过程中过程会从 用户态进入到内核态,最初会调用到 sock_sendmsg
办法。
而后进入传输层,带上 TCP
头。网络层带上 IP
头,数据链路层带上 MAC
头等一系列操作后。进入网卡的 发送队列 ring buffer,顺着网卡就收回去了。
回到 ping
,整个过程也根本跟 TCP
发数据相似,差别的中央次要在于,创立 socket
的时候用的是 socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)
,SOCK_RAW
是原始套接字,工作在网络层 ,所以构建ICMP
(网络层协定)的数据,是再适合不过了。ping 在进入内核态后最初也是调用的 sock_sendmsg
办法,进入到网络层后加上ICMP 和 IP 头 后,数据链路层加上MAC 头,也是顺着网卡收回。因而 实质上 ping 跟 一般利用发消息 在程序流程上没太大差异。
这也解释了 为什么当你发现狐疑网络有问题的时候,他人第一工夫是问你能 ping 通吗?因为能够简略了解为 ping 就是本人组了个数据包,让零碎按着其他软件发送数据的门路往外发一遍,能通的话阐明其他软件发的数据也能通。
为什么断网了还能 ping 通 127.0.0.1
后面提到,有网的状况下,ping 最初是 通过网卡 将数据发送进来的。
那么断网的状况下,网卡曾经不工作了,ping 回环地址却一切正常,咱们能够看下这种状况下的工作原理。
从应用层到传输层再到网络层。这段门路跟 ping 外网的时候是简直是一样的。到了网络层,零碎会依据目标 IP,在路由表中获取对应的 路由信息 ,而这其中就蕴含抉择 哪个网卡 把音讯收回。
当发现 指标 IP 是外网 IP时,会从 ” 真网卡 ” 收回。
当发现 指标 IP 是回环地址 时,就会抉择 本地网卡。
本地网卡,其实就是个 “ 假网卡 ”,它不像 ” 真网卡 ” 那样有个ring buffer
什么的,” 假网卡 ” 会把数据推到一个叫 input_pkt_queue
的 链表 中。这个链表,其实是所有网卡共享的,下面挂着发给本机的各种音讯。音讯被发送到这个链表后,会再触发一个 软中断。
专门解决软中断的工具人 “ksoftirqd”(这是个 内核线程),它在收到软中断后就会立马去链表里把音讯取出,而后顺着数据链路层、网络层等层层往上传递最初给到应用程序。
ping 回环地址和 通过 TCP 等各种协定发送数据到回环地址 都是走这条门路。整条门路从发到收,都没有通过 ” 真网卡 ”。之所以 127.0.0.1 叫本地回环地址,能够了解为,音讯收回到这个地址上的话,就不会出网络,在本机打个转就又回来了。所以断网,仍然能 ping
通 127.0.0.1
。
ping 回环地址和 ping 本机地址有什么区别
咱们在 mac 里执行 ifconfig
。
$ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet 127.0.0.1 netmask 0xff000000
...
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 192.168.31.6 netmask 0xffffff00 broadcast 192.168.31.255
...
能看到 lo0,示意本地回环接口,对应的地址,就是咱们后面提到的 127.0.0.1,也就是 回环地址。
和 eth0,示意本机第一块网卡,对应的 IP 地址是 192.168.31.6,管它叫 本机 IP。
之前始终认为 ping 本机 IP 的话会通过 ” 真网卡 ” 进来,而后遇到第一个路由器,再发回来到本机。
为了验证这个说法,能够进行抓包,但后果跟下面的说法并不相同。
能够看到 ping 本机 IP 跟 ping 回环地址一样,相干的网络数据,都是走的 lo0,本地回环接口,也就是后面提到的“ 假网卡 ”。
只有走了本地回环接口,那数据都不会发送到网络中,在本机网络协议栈中兜一圈,就发回来了。因而 ping 回环地址和 ping 本机地址没有区别。
127.0.0.1 和 localhost 以及 0.0.0.0 有区别吗
回到文章结尾动图里的发问,算是面试八股文里的老常客了。
以前第一次用 nginx
的时候,发现用这几个 IP
,都能失常拜访到 nginx
的欢送网页。一度认为这几个 IP
都是一样的。
但实质上还是有些区别的。
首先 localhost
就不叫 IP
,它是一个域名,就跟 "baidu.com"
, 是一个模式的货色,只不过默认会把它解析为 127.0.0.1
,当然这能够在 /etc/hosts
文件下进行批改。
所以默认状况下,应用 localhost
跟应用 127.0.0.1
的确是没区别的。
其次就是 0.0.0.0
,执行 ping 0.0.0.0,是会失败的,因为它在 IPV4
中示意的是有效的 指标地址。
$ 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
但它还是很有用途的,回忆下,咱们启动服务器的时候,个别会 listen
一个 IP 和端口,期待客户端的连贯。
如果此时 listen
的是本机的 0.0.0.0
, 那么它示意本机上的 所有 IPV4 地址。
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000) /* 0.0.0.0 */
举个例子。刚刚提到的 127.0.0.1
和 192.168.31.6
,都是本机的 IPV4 地址,如果监听 0.0.0.0
,那么用下面两个地址,都能拜访到这个服务器。
当然,客户端 connect
时,不能应用 0.0.0.0
。必须指明要连贯哪个服务器 IP。
总结
127.0.0.1
是 回环地址 。localhost
是域名,但默认等于127.0.0.1
。ping
回环地址和ping
本机地址,是一样的,走的是 lo0 “ 假网卡 ”,都会通过网络层和数据链路层等逻辑,最初在快要出网卡前 狠狠拐了个弯 ,将数据插入到一个 链表 后就 软中断 告诉 ksoftirqd 来进行 收数据 的逻辑,压根就不出网络。所以断网了也能ping
通回环地址。- 如果服务器
listen
的是0.0.0.0
,那么此时用127.0.0.1
和本机地址 都能够 拜访到服务。
最初
最近工作上的事件太忙,原本就黑的黑眼圈,就更黑了,鸽了大家这么久切实不好意思哈。
这篇文章里,有几张大图原本都是动图,然而发现动起来之后发现字太小,点开来放大之后图又不会动了。有些影响体验,我就先改成动态图吧。
欢送大家加我微信(公众号里右下角“分割我”),相互围观朋友圈砍一刀啥的哈哈。
如果文章对你有帮忙,看下文章底部右下角,做点正能量的事件(点两下 )反对一下。( 疯狂暗示,托付托付,这对我真的很重要!)
我是小白,咱们下期见。
参考资料
《127.0.0.1 之本机网络通信过程知多少 ?!》—— 举荐关注飞哥的《开发内功修炼》
文章举荐:
- 动图图解!既然 IP 层会分片,为什么 TCP 层也还要分段?
- 动图图解!GMP 模型里为什么要有 P?背地的起因让人暖心
- i/o timeout,心愿你不要踩到这个 net/http 包的坑
- 妙啊! 程序猿的第一本互联网黑话指南
- 程序员防猝死指南
- 我感觉,我可能要拿图灵奖了。。。
- 给大家争脸了,用了三年 golang,我还是没答对这道内存透露题
- 硬核!漫画图解 HTTP 知识点 + 面试题
- TCP 粘包 数据包:我只是犯了每个数据包都会犯的错 | 硬核图解
- 硬核图解!30 张图带你搞懂!路由器,集线器,交换机,网桥,光猫有啥区别?
别说了,一起在常识的陆地里呛水吧
关注公众号:【golang 小白成长记】