Go語言如何獲取網卡信息
net
網絡接口
函數(shù)
func Interfaces() ([]Interface, error) {}- 返回系統(tǒng)網絡接口的列表
func InterfaceAddrs() ([]Addr, error) {}- 返回一個系統(tǒng)單播接口地址的列表
- 該列表無法標識關聯(lián)的接口
- 用Interfaces和Interface.Addrs獲取更詳細信息
func InterfaceByIndex(index int) (*Interface, error) {}- 返回索引對應的接口
func InterfaceByName(name string) (*Interface, error) {}- 返回名字對應的接口
類型
Interface
包含:索引(Index),MTU,名字(Name),硬件地址(HardwareAddr),標志位(up | broadcast | multicast)信息
Windows下的例子:
{Index:13 MTU:1500 Name:以太網 HardwareAddr:b8:85:84:bb:6a:36 Flags:up|broadcast|multicast}{Index:1 MTU:-1 Name:Loopback Pseudo-Interface 1 HardwareAddr: Flags:up|loopback|multicast}
type Interface struct {
Index int // positive integer that starts at one, zero is never used
MTU int // maximum transmission unit
Name string // e.g., "en0", "lo0", "eth0.100"
HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form
Flags Flags // e.g., FlagUp, FlagLoopback, FlagMulticast
}
- Addr
- 代表一個網絡端點地址
示例:
String():“192.0.2.1:25”, “[2001:db8::1]:80”, “127.0.0.1/8”Network():“tcp”, “udp”, “ip+net”
type Addr interface {
Network() string // name of the network (for example, "tcp", "udp", "ip+net")
String() string // string form of address (for example, )
}
syscall
網絡接口
原本是go 1.5之前interface_windows.go下的源碼,后來被移除了。
func getAdapterList() (*syscall.IpAdapterInfo, error) {
b := make([]byte, 1000)
l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
err := syscall.GetAdaptersInfo(a, &l)
if err == syscall.ERROR_BUFFER_OVERFLOW {
b = make([]byte, l)
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
err = syscall.GetAdaptersInfo(a, &l)
}
if err != nil {
return nil, os.NewSyscallError("GetAdaptersInfo", err)
}
return a, nil
}
getAdapterList()
返回一個*syscall.IpAdapterInfo鏈表,通過Next指向下一個網卡。
| 字段名 | 解釋 | 類型 | 示例 |
|---|---|---|---|
| Index | 索引 | uint32 | 13 |
| AdapterName | 適配器ID | []uint8 | {5C9384EF-DEBA-43A6-AE6A-5D10C952C481} |
| Description | 描述 | []uint8 | Intel® Ethernet Connection (7) I219-LM |
| DhcpEnabled | DHCP狀態(tài) | uint32 | 1 |
| IpAddressList | ip鏈表 | syscall.IpAddrString | {IpAddress:“192.168.13.31”, IpMask:“255.255.255.0”} |
| GatewayList | 網關鏈表 | syscall.IpAddrString | {IpAddress:“192.168.13.1”, IpMask:“255.255.255.255”} |
| DhcpServer | DHCP服務器鏈表 | syscall.IpAddrString | {IpAddress:“192.168.13.254”, IpMask:“255.255.255.255”} |
type IpAdapterInfo struct {
Next *IpAdapterInfo
ComboIndex uint32
AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]byte
Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]byte
AddressLength uint32
Address [MAX_ADAPTER_ADDRESS_LENGTH]byte
Index uint32
Type uint32
DhcpEnabled uint32
CurrentIpAddress *IpAddrString
IpAddressList IpAddrString
GatewayList IpAddrString
DhcpServer IpAddrString
HaveWins bool
PrimaryWinsServer IpAddrString
SecondaryWinsServer IpAddrString
LeaseObtained int64
LeaseExpires int64
}
github.com/google/gopacket/pcap
網絡接口
函數(shù)
func FindAllDevs() (ifs []Interface, err error) {}- 返回
Interface列表
類型
Interface- 描述了機器上一個單獨的網絡接口
- 包含:名字(Name),描述,標志位,地址(
InterfaceAddress列表)信息
示例:

type Interface struct {
Name string
Description string
Flags uint32
Addresses []InterfaceAddress
}
type InterfaceAddress struct {
IP net.IP
Netmask net.IPMask // Netmask may be nil if we were unable to retrieve it.
Broadaddr net.IP // Broadcast address for this IP may be nil
P2P net.IP // P2P destination address for this IP may be nil
}
處理網絡流
函數(shù)
func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error) {}
func OpenOffline(file string) (handle *Handle, err error) {}
func OpenOfflineFile(file *os.File) (handle *Handle, err error) {}獲取網卡信息的各種方法測試
package main
import (
"fmt"
"github.com/google/gopacket/pcap"
"log"
"net"
"os"
"syscall"
"unsafe"
)
func getAdapterList() (*syscall.IpAdapterInfo, error) {
b := make([]byte, 1000)
l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
err := syscall.GetAdaptersInfo(a, &l)
if err == syscall.ERROR_BUFFER_OVERFLOW {
b = make([]byte, l)
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
err = syscall.GetAdaptersInfo(a, &l)
}
if err != nil {
return nil, os.NewSyscallError("GetAdaptersInfo", err)
}
return a, nil
}
func localAddresses() error {
fmt.Println("測試net.Interfaces()\n")
ifaces, err := net.Interfaces()
if err != nil {
return err
}
for _, iface := range ifaces {
fmt.Printf("%+v\n", iface)
}
fmt.Println()
fmt.Println("測試net.InterfaceAddrs()")
addrs, err := net.InterfaceAddrs()
if err != nil {
return err
}
for _, addr := range addrs {
fmt.Printf("\n%+v\n", addr.String())
fmt.Printf("%+v\n", addr.Network())
}
fmt.Println()
//net.InterfaceByIndex()
//net.InterfaceByName()
//for _, addr := range addrs {
// fmt.Printf("%T", addr)
// // 這個網絡地址是IP地址: ipv4, ipv6
// ipNet1, isIpNet1 := addr.(*net.IPNet)
// fmt.Println(ipNet1)
// fmt.Println(isIpNet1)
// if ipNet, isIpNet := addr.(*net.IPNet); isIpNet && !ipNet.IP.IsLoopback() {
// // 跳過IPV6
// if ipNet.IP.To4() != nil {
// ipv4 := ipNet.IP.String() // 192.168.1.1
// fmt.Println(ipv4)
// }
// }
//}
fmt.Println("測試基于syscall的getAdapterList()")
aList, err := getAdapterList()
if err != nil {
return err
}
for ai := aList; ai != nil; ai = ai.Next {
fmt.Printf("\nIndex:\t%v\n", ai.Index)
fmt.Printf("AdapterName:\t%s\n", &ai.AdapterName)
fmt.Printf("Description:\t%s\n", &ai.Description)
fmt.Printf("Address:\t%s\n", &ai.Address)
ipl := &ai.IpAddressList
gwl := &ai.GatewayList
dhcpl := &ai.DhcpServer
for ; ipl != nil; ipl = ipl.Next {
fmt.Printf("IpAddress:\t%s\n", ipl.IpAddress)
fmt.Printf("IpMask:\t%s\n", ipl.IpMask)
fmt.Printf("GatewayIp:\t%s\n", gwl.IpAddress)
fmt.Printf("DHCPServerIp:\t%s\n", dhcpl.IpAddress)
}
}
fmt.Println()
return err
}
func main() {
if e := localAddresses(); e != nil {
fmt.Println(e)
}
fmt.Println("測試pcap.FindAllDevs()")
// Find all devices
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
// Print device information
for _, device := range devices {
fmt.Println("\nName: ", device.Name)
fmt.Println("Description: ", device.Description)
fmt.Println("Devices Flags: ", device.Flags)
fmt.Println("Devices addresses: ")
for _, address := range device.Addresses {
fmt.Println("- IP address: ", address.IP)
fmt.Println("- Subnet mask: ", address.Netmask)
fmt.Println("- Broadaddr: ", address.Broadaddr)
}
}
}
問題
如何關聯(lián)各種信息?
比如關聯(lián)pcap.Interface和net.Interface,參考:How to associate pcap.Interface with net.Interface?,有個人提出了一個解決方案,by matching the IP addresses of the interfaces with those of the devices。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

