利用 mDNS 协议来定位局域网主机
再也不用费劲去找树莓派的 IP 地址了!你的操作系统自带了“网络发现”功能。
在一个平常的局域网(开启了 DHCP)下面,获得一台主机的 IP 地址常常有这么几种方法:
- 用
arp -a
命令查询 arp 缓存; - 在目标主机上查找本机的 IP 地址,使用例如
ipconfig
命令; - 浏览器登录路由器的后台,从连接的主机列表中查找;
- 给目标主机设置静态IP。
不久之前,我一直用上面的方法来连接我的树莓派。树莓派没接显示器,没办法在主机上操作,每次要么使用手机热点(设备管理里面能显示 IP),要么直接改配置分配静态IP。这些方法都有局限性,网络环境一变化,又得配置半天。
现在,一个新的方法出现了!(其实一直就有)只要知道你的设备的主机名,你就可以得到你的设备的
IP 地址。例如,我的树莓派是 Raspbian 系统,它的默认主机名是
raspberrypi
,就可以通过域名 raspberrypi.local
来连接,像这样:
1 | ssh pi@raspberrypi.local |
这就是 mDNS (Multicast DNS)协议给我们提供的便利。
偶然的发现
在研究 IGMP 协议的时候,我用 Wireshark 对无线网卡抓取 IGMP 数据包,想看看有没有什么服务是在使用组播(Multicast)地址的。

之后我看到了局域网内的电脑基本上都会加入这几个组播地址:224.0.0.251
,224.0.0.252
,239.255.255.250
。
经过查找,这三个组播地址分别是协议 mDNS,LLMNR 和 SSDP 协议的。mDNS实现了类似 DNS 的功能,使得主机在局域网内能够加入和通信;LLMNR 的功能和 mDNS 类似;SSDP 是 UPnP 协议的一部分,也是用来实现设备和服务的发现的。
在一段 mDNS 报文中,我看到了这样的内容:
1 | Multicast Domain Name System (response) |
来源是 192.168.10.108
,目的是 224.0.0.251
。
返回的记录中有我的树莓派的 IPv4 和 IPv6 地址,以及一个相同的字段
raspberrypi.local
。
难道说 raspberrypi.local
就是我树莓派的域名?我立马 ping
了一下:
1 | PS C:\WINDOWS\system32> ping raspberrypi.local |
确实可以。我流下了激动的泪水:这么好的东西怎么没早发现呢!
mDNS 查询过程
通过分析抓包数据,mDNS 协议在局域网内的 IP 地址查询过程大致是这样的:
A:发起查询的主机
B:被查询的主机
- A,B 在加入网络时都会发 IGMP 报文加入组
224.0.0.251
; - A 向组
224.0.0.251
发送 mDNS 组播报文查询 B 的主机名,所有在组内的主机都会收到这个查询请求; - B 向组
224.0.0.251
发送回应 mDNS 报文,内容包括自己的主机名和 IP 地址; - A 得到 B 的 IP 地址。
其中,mDNS 报文是包装在 UDP 组播报文中的,使用 5353
端口。
主机名的查询和修改
Windows 系统的主机名在环境变量 COMPUTERNAME
查看,可以在系统设置中修改。
1 | echo %COMPUTERNAME% |

Linux 系统主机名存在 /etc/hostname
中。使用
hostnamectl
可以查询和修改。/etc/hosts
里也有主机名的记录,也要一并修改。
1 | 查询主机名 |
我的系统支持吗
Windows 10 以后,系统就能够支持 mDNS 协议了。Windows 10 以下的系统怎么办?你可以:
给 Windows 安装苹果公司的 Bonjour,只有 5 Mb 大小,推荐。
使用 NetBIOS 协议,这是微软的网络发现服务。Linux 系统上安装
samba
,它的nmbd
服务使得能被 Windows 主机发现。使用方法:- Windows上:主机名即为域名。主机名是 raspberrypi,直接
ping raspberrypi
。 - Linux上:默认不解析 NetBIOS 主机名,使用
nmblookup 主机名
来得到 Windows 主机 IP。如果要实现解析 NetBIOS 主机名,需要修改配置文件,没折腾了,看这篇文章 -> 在 Linux 解析 Netbios 名稱。
- Windows上:主机名即为域名。主机名是 raspberrypi,直接
Linux 一般是安装了 avahi-daemon
服务。使用指令
systemctl status avahi-daemon.service
来查看服务运行状态。

安卓系统似乎不支持,我的华为手机没有。
还可以查询 UDP 5353 端口。
Windows:
1 | netstat -ano | findstr 5353 |
Linux:
1 | sudo netstat -nap | grep 5353 |
其实最简单的就是 ping 一下 主机名.local 看看有没有就知道了。
参见:
利用 mDNS 协议来定位局域网主机
https://blog.beanbang.cn/2019/08/07/locate-hosts-using-mdns/