主题
网络工具例程 6:周期 Ping 多个目标(定时器 + net.ping)
这一页只讲这一个例程。同组其余例程、以及这个库的函数说明都在 05-05-net。
适用:同上 | 依赖模块:net timer | 难度:★☆☆
场景:同时盯着两个目标的连通性——比如本地网关(内网通不通)和公网站点(外网通不通),各用一个 5 秒定时器周期探测。
完整代码(可直接下载运行):
lua
-- 每 5 秒探一次本地网关
timeobj = timer.start(5000, function()
net.ping("192.168.1.1", function(message)
print(message)
end)
end)
-- 每 5 秒探一次公网(域名也行,会自动 DNS 解析)
timeobj2 = timer.start(5000, function()
net.ping("www.baidu.com", function(message)
print(message)
end)
end)实际运行会按目标逐个打印(公网偶尔丢首包,所以可能先看到一次超时,下一轮又通了):
text
来自 192.168.1.1 的回复: 时间=11.44ms TTL=64
ping www.baidu.com (103.235.46.115) 失败: 请求超时
来自 www.baidu.com (103.235.46.115) 的回复: 时间=311.75ms TTL=47要点:
net.ping必须传 2 个参数:目标(IP 或域名)+ 结果回调。- 回调收到的是已格式化的中文结果串("来自 … 的回复" 或 "ping … 失败: …"),不是结构化数值,要判连通就用
msg:match("回复")。 - 域名解析失败也走这个回调,和超时一样在串里给出原因。
- 周期调用是安全的:
net.ping现已改为异步(worker 线程里做阻塞 ping,结果通过消息泵回主线程、在 Lua 线程里用回调返回),不会卡住您的 Lua 主线程。每次 ping 都用自己短生命周期的 socket、用完即关(RAII 析构关闭),即使定时器密集触发也不会泄漏,可放心长期挂定时器跑。
验证方法:
能上内/外网时,两个定时器都打印"回复"。
拔掉网线或网关断电,对应那条变成"失败: 请求超时",另一条不受影响。
确认无 socket 泄漏:反复触发 ping 后设备仍能正常响应、不重启,就说明用完即关成立(每次 ping 都用自己的短生命周期 socket,函数返回即释放)。 如果手上是调试版固件,还能直接读计数器核对:
luafor i = 1, 200 do net.ping("127.0.0.1", function() end) end local s = net.ping_stats() -- 返回 {created=累计建 socket 次数, closed=累计关 socket 次数} print(s.created, s.closed) -- 两者相等即无泄漏net.ping_stats()只在调试版固件里存在,出厂的正式固件调用它会报attempt to call a nil value。 另外它返回的是表,print(net.ping_stats())只会打出table: 0x…,要取created/closed两个字段来看。
注意事项:
- 回调结果不能直接当数值比较,要用
match("回复")之类判断。 net.ping不再阻塞主线程(已改为异步):您调用它后立即返回,结果稍后由回调给出;底层 worker 单次 ping 仍最多等 5 秒超时,但那 5 秒发生在 worker 线程里,不占主线程。多个定时器并发 ping 也安全;只是若短时间内堆积太多 ping,会同时开多个短生命周期 socket,建议定时器间隔 ≥ 5 秒,避免瞬时占用过多。