通过 UPnP 协议监测路由器的流量
· 约 1 分钟阅读
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。