通过 UPnP 协议监测路由器的流量
UPnP 即“通用即插即用”(Universal Plug and Play),能让网络设备自动发现和配置,实现互联互通。基于 UPnP,路由器能与设备更好交互,为监测路由器流量提供便利,助用户管理网络。对于支持 UPnP 且开启了 UPnP 的路由器,可通过特定接口访问路由器的状态信息。
开源的智能家居自动化平台 Home Assistant 内置了对 UPnP 设备的支持,在添加了 UPnP/IGD 设备后,即可看到局域网内的路由器,并且获取路由器的上传和下载速率。下文以简单的代码示例,介绍通过 Golang 代码获取路由器的流量数据的方法。
UPnP库 🔗
huin/goupnp 是一个 Go语言的 UPnP 客户端库。
实现思路 🔗
基于当前的 goupnp
库,想要获取路由器的流量数据,包括如下几步:
- 通过 UPnP 协议,发现当前网络中的服务实例。
- 针对每个实例,获取当前的已接收和已发送的字节数。已接收即下载,已发送即上传。
- 等待一定时间,针对每个实例,再次获取获取当前的已接收和已发送的字节数。
- 根据两次获取到的字节数和间隔时间,计算下载和上传速度。
代码示例 🔗
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/huin/goupnp/dcps/internetgateway1"
)
func main() {
if err := invoke(); err != nil {
log.Fatalln(err)
}
}
type Speed struct {
Device string
Upload float64
Download float64
}
func invoke() error {
clients, errors, err := internetgateway1.NewWANCommonInterfaceConfig1ClientsCtx(context.Background())
if err != nil {
return fmt.Errorf("Error discovering service with UPnP: %v", err)
}
if len(errors) > 0 {
return fmt.Errorf("Error discovering services: %v", errors)
}
interval := 2 * time.Second
for _, client := range clients {
oldRecv, err := client.GetTotalBytesReceivedCtx(context.Background())
if err != nil {
return fmt.Errorf("Error requesting bytes received: %v", err)
}
oldSent, err := client.GetTotalBytesSentCtx(context.Background())
if err != nil {
return fmt.Errorf("Error requesting bytes sent: %v", err)
}
time.Sleep(interval)
newRecv, err := client.GetTotalBytesReceived()
if err != nil {
return fmt.Errorf("Error requesting bytes received: %v", err)
}
newSent, err := client.GetTotalBytesSent()
if err != nil {
return fmt.Errorf("Error requesting bytes sent: %v", err)
}
downloadSpeed := float64(newRecv-oldRecv) / interval.Seconds()
uploadSpeed := float64(newSent-oldSent) / interval.Seconds()
fmt.Printf("%s\tDownload:%.2f KB/s\tUpload:%.2f KB/s\n", client.RootDevice.Device.FriendlyName, downloadSpeed/1000, uploadSpeed/1000)
}
return nil
}
其他 🔗
如果调试上面的代码,可以发现上述代码访问了 IGD 接口、IFC 接口等。我的路由器地址为 192.168.1.1
,它们的地址分别是 http://192.168.1.1:1900/igd.xml
和 http://192.168.1.1:1900/ifc.xml
。
加载中...