项目初始化
This commit is contained in:
134
internal/netstat/netstat.go
Normal file
134
internal/netstat/netstat.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package netstat
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// InterfaceStats 网卡统计信息
|
||||
|
||||
type InterfaceStats struct {
|
||||
Name string //网卡名称
|
||||
RxBytes uint64 //接收字节数
|
||||
TxBytes uint64 //发送字节数
|
||||
RxPackets uint64 //接收数据包数
|
||||
TxPackets uint64 //发送数据包数
|
||||
RxErrors uint64 //接收错误数
|
||||
TxErrors uint64 //发送错误数
|
||||
}
|
||||
type TrafficRate struct {
|
||||
Name string // 网卡名称
|
||||
RxBytesRate float64 // 接收字节速率
|
||||
TxBytesRate float64 // 发送字节速率
|
||||
RxKbps float64 // 接收比特速率
|
||||
TxKbps float64 // 发送比特速率
|
||||
}
|
||||
|
||||
// GetInterfaceStats 获取所有网卡的统计信息
|
||||
func GetInterfaceStats() ([]InterfaceStats, error) {
|
||||
// 打开/proc/net/dev文件
|
||||
file, err := os.Open("/proc/net/dev")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 创建scanner逐行读取文件内容
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
// 跳过前两行 头部信息
|
||||
scanner.Scan()
|
||||
scanner.Scan()
|
||||
|
||||
var stats []InterfaceStats
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
// 按空格分割
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 17 {
|
||||
continue
|
||||
}
|
||||
// 提取网卡名
|
||||
ifaceName := strings.TrimSuffix(fields[0], ":")
|
||||
if ifaceName == "lo" {
|
||||
continue //跳过回环接口
|
||||
}
|
||||
|
||||
stat := InterfaceStats{
|
||||
Name: ifaceName,
|
||||
RxBytes: parseUint64(fields[1]),
|
||||
RxPackets: parseUint64(fields[2]),
|
||||
RxErrors: parseUint64(fields[3]),
|
||||
TxBytes: parseUint64(fields[9]),
|
||||
TxPackets: parseUint64(fields[10]),
|
||||
TxErrors: parseUint64(fields[11]),
|
||||
}
|
||||
stats = append(stats, stat)
|
||||
}
|
||||
return stats, scanner.Err()
|
||||
}
|
||||
|
||||
func parseUint64(s string) uint64 {
|
||||
var val uint64
|
||||
fmt.Sscanf(s, "%d", &val)
|
||||
return val
|
||||
}
|
||||
|
||||
func CalculateRate(prev, curr []InterfaceStats, duration time.Duration) []TrafficRate {
|
||||
prevMap := make(map[string]InterfaceStats)
|
||||
for _, stat := range prev {
|
||||
prevMap[stat.Name] = stat
|
||||
}
|
||||
var rates []TrafficRate
|
||||
seconds := duration.Seconds()
|
||||
for _, c := range curr {
|
||||
p, exists := prevMap[c.Name]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
rxBytesDiff := c.RxBytes - p.RxBytes
|
||||
txBytesDiff := c.TxBytes - p.TxBytes
|
||||
rate := TrafficRate{
|
||||
Name: c.Name,
|
||||
RxBytesRate: float64(rxBytesDiff) / seconds,
|
||||
TxBytesRate: float64(txBytesDiff) / seconds,
|
||||
RxKbps: (float64(rxBytesDiff) * 8) / (seconds * 1024),
|
||||
TxKbps: (float64(txBytesDiff) * 8) / (seconds * 1024),
|
||||
}
|
||||
rates = append(rates, rate)
|
||||
}
|
||||
return rates
|
||||
}
|
||||
|
||||
func FormatBytes(bytes float64) string {
|
||||
const unit = 1024
|
||||
if bytes < unit {
|
||||
return fmt.Sprintf("%.2f B", bytes)
|
||||
}
|
||||
div, exp := uint64(unit), 0
|
||||
for n := bytes / unit; n >= unit; n /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
return fmt.Sprintf("%.2f %cB", bytes/float64(div), "KMGTPE"[exp])
|
||||
}
|
||||
|
||||
// FormatBps 格式化比特率为 1.23 Kbps、4.56 Mbps 等
|
||||
func FormatBps(bps float64) string {
|
||||
const unit = 1000
|
||||
if bps < unit {
|
||||
return fmt.Sprintf("%.2f bps", bps)
|
||||
}
|
||||
|
||||
div, exp := float64(unit), 0
|
||||
for n := bps / unit; n >= unit; n /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%.2f %cps", bps/div, "KMGTPE"[exp])
|
||||
}
|
||||
Reference in New Issue
Block a user