golang执行ip addr list并获取网卡及其绑定ip

文章介绍了如何在Golang中通过执行Linux的`ipaddrlist`命令来获取系统网卡及绑定的IP地址,因为`net.Interfaces()`无法获取未绑定的IP。作者编写了一个函数`getClientIpsByCmd`来执行命令并解析输出,利用正则表达式匹配IP和MAC地址信息,最后提供了测试案例展示如何获取并显示多个网卡的IP配置详情。

最近工作中需要获取系统网卡及绑定ip,方便管理ip,最开始使用golang的

net.Interfaces()

获取不到未绑定ip的网卡,于是打算使用linux ip指令获取,于是记录一下笔记;

1.golang 执行ip add list 获取结果

func getClientIpsByCmd() (ipMap []ClientIpMap, err error) {
	var out bytes.Buffer
	var stdErr bytes.Buffer
	cmd := exec.Command("bash", "-c", `ip addr list`)
	cmd.Stdout = &out
	cmd.Stderr = &stdErr
	err = cmd.Run()
	if err != nil {
		return
	}
	if stdErr.String() != "" {
		err = errors.New(stdErr.String())
		return
	}
	ipMap = spit(out.String())
	return
}

 通过正则匹配解析

type IpMap struct {
	Ip  string
	Mac string
}

type ClientIpMap struct {
	Name string
	Ips  []IpMap
}

func spit(s string) []ClientIpMap {
	cardList := make([]ClientIpMap, 0)
	compile := regexp.MustCompile(`[^a-z0-9][0-9]+:\s+`)
	split := compile.Split(s, -1)
	for i, sp := range split {
		if i == 0 {
			sp = strings.TrimLeft(sp, "1: ")
		}
		ipMap, err := match(sp)
		if err != nil {
			continue
		}
		cardList = append(cardList, ipMap)
	}
	return cardList
}

func match(s1 string) (ClientIpMap, error) {
	compile := regexp.MustCompile(`(?m)(^[a-z0-9\-]+):[\s\S]*([a-z0-9]{2}:[a-z0-9]{2}:[a-z0-9]{2}:[a-z0-9]{2}:[a-z0-9]{2}:[a-z0-9]{2})\s+[brd][\s\S]*`)
	submatch := compile.FindStringSubmatch(s1)

	if len(submatch) < 3 {
		return ClientIpMap{}, errors.New("无效")
	}
	// 匹配ip
	mustCompile := regexp.MustCompile(`(?m)[inet]\s+(\d+\.\d+\.\d+\.\d+)`)
	stringSubmatch := mustCompile.FindAllStringSubmatch(s1, -1)
	ips := make([]IpMap, 0)
	for _, sb := range stringSubmatch {
		if l := len(sb); l > 0 {
			// fmt.Println(sb[l-1])
			ips = append(ips, IpMap{
				Ip:  sb[l-1],
				Mac: submatch[2],
			})
		}
	}

	return ClientIpMap{
		Name: submatch[1],
		Ips:  ips,
	}, nil

}

3.测试

var s = `1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/32 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 0a:8f:d6:1c:a8:00 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.107/24 brd 192.168.2.255 scope global dynamic eth0
       valid_lft 4924sec preferred_lft 4924sec
    inet 192.168.2.132/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::88f:d6ff:fe1c:a800/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 7a:75:c2:49:37:f1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.140/24 brd 192.168.2.255 scope global dynamic eth1
       valid_lft 4659sec preferred_lft 4659sec
    inet 192.168.2.132/32 scope global eth1
       valid_lft forever preferred_lft forever
    inet 192.168.3.132/24 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::7875:c2ff:fe49:37f1/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether b2:5b:10:12:91:db brd ff:ff:ff:ff:ff:ff
5: eth3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 36:a4:d2:43:b6:d4 brd ff:ff:ff:ff:ff:ff`


func Test_GetIPs(t *testing.T) {
	ipMap, err := tools.NewIpServer().GetIps()
	fmt.Printf("res:%-v err:%v", ipMap, err)
}

结果:

Golang学习专栏收录该内容23 篇文章订阅专栏本文详细介绍了网络协议的典型协议及其分层模型,包括物理层、数据链路层、网络层、传输层和应用层的功能及常用协议。接着讲解了Socket编程的概念,阐述了TCP/IP的C/S架构,展示了简单的客户端和服务端通信流程,探讨了发服务器的实现。此外,文章还对比了TCP和UDP的差异,通过实例展示了文件传输的流程。最后,构建了一个发聊天室的模型,涵盖了用户上线广播、消息传递、在线用户展示、用户改名和超时处理等功能。文章目录一、网络协议:1. 典型协议:2.分层模型:2.1 网络分层架构:2.2 层与协议:2.3 通信过程2.4 总结通信过程:二、Socket编程:1.什么是Socket:2. 网络应用程序设计模式:2.1 模式:2.2 TCP的C/S架构:2.3 简单的C/S模型通信:a.Server端:b.Client 端:2.4 发的C/S模型通信:a.发server:b.发Client3. TCP通信3.1 三次握手:3.2 四次挥手:4. UDP:4.1 UDP服务器4.2 UDP客户端:4.3 UDP发:5.UDP与TCP的差异三、实例 -- 文件传输:1. 流程简析2. 获取文件属性:3. 客户端实现4.服务端实现:四、示例 - 发聊天室:1 模块简述2. 广播用户上线3. 广播用户消息4. 展示在线用户:5. 修改用户名:5. 用户退出与超时处理:一、网络协议:1. 典型协议:传输层: 常见协议有TCP/UDP协议;应用层: 常见的协议有HTTP协议,FTP协议;网络层: 常见协议有IP协议、ICMP协议、IGMP协议;网络接口层: 常见协议有ARP协议、RARP协议;TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议;UDP用户数据报协议(User Datagram Protocol)是OSI参考模型中一种无连接的传输层协议, 提供面向事务的简单不可靠信息传送服务;HTTP超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议;FTP文件传输协议(File Transfer Protocol)IP协议是因特网互联协议(Internet Protocol)ICMP协议是Internet控制报文协议(Internet Control Message Protocol): 它是TCP/IP协议族的一个子协议, 用于在IP主机、路由器之间传递控制消息;IGMP协议是 Internet 组管理协议(Internet Group Management Protocol), 是因特网协议家族中的一个组播协议; 该协议运行在主机和组播路由器之间;ARP协议是正向地址解析协议(Address Resolution Protocol) 通过已知的IP, 寻找对应主机的MAC地址;RARP是反向地址转换协议, 通过MAC地址确定IP地址;2.分层模型:2.1 网络分层架构:为了减少协议设计的复杂性, 大多数网络模型均采用分层的方式来组织; 每一层都有自己的功能, 就像建筑物一样, 每一层都靠下一层支持; 每一层利用下一层提供的服务来为上一层提供服务, 本层服务的实现细节对上层屏蔽;业内普遍的分层方式有两种: OSI七层模型 和 TCP/IP四层模型, 可以通过背诵两个口诀来快速记忆:OSI七层模型: 物、数、网、传、会、表、应;TCP/IP四层模型: 链、网、传、应;物理层: 主要定义物理设备标准, 如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等; 它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输, 到达目的地后再转化为1、0, 也就是我们常说的数模转换与模数转换); 这一层的数据叫做比特;数据链路层: 定义了如何让格式化数据以帧为单位进行传输, 以及如何让控制对物理介质的访问; 这一层通常还提供错误检测和纠正, 以确保数据的可靠传输; 如:串口通信中使用到的115200、8、N、1;网络层: 在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择; Internet的发展使得从世界各站点访问信息的用户数大大增加, 而网络层正是管理这种连接的层;传输层: 定义了一些传输数据的协议和端口号(WWW端口80等), 如: TCP(传输控制协议, 传输效率低, 可靠性强, 用于传输可靠性要求高, 数据量大的数据); UDP(用户数据报协议, 与TCP特性恰恰相反, 用于传输可靠性要求不高, 数据量小的数据, 如QQ聊天数据就是通过这种方式传输的); 主要是将从下层接收的数据进行分段和传输, 到达目的地址后再进行重组; 常常把这一层数据叫做段;会话层: 通过传输层(端口号: 传输端口与接收端口)建立数据传输的通路; 主要在系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC地址或者是主机名)。表示层: 可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取; 例如: PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符; 如有必要, 表示层会通过使用一种通用格式来实现多种数据格式之间的转换;应用层: 是最靠近用户的OSI层; 这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务;2.2 层与协议:每一层都是为了完成一种功能, 为了实现这些功能, 就需要大家都遵守共同的规则; 大家都遵守这规则, 就叫做协议(protocol);网络的每一层, 都定义了很多协议; 这些协议的总称, 叫TCP/IP协议; TCP/IP协议是一个大家族, 不仅仅只有TCP和IP协议, 它还包括其它的协议, 如下图:协议功能:链路层:以太网规定, 连入网络的所有设备, 都必须具有网卡接口; 数据包必须是从一块网卡, 传送到另一块网卡; 通过网卡能够使不同的计算机之间连接, 从而完成数据通信等功能; 网卡的地址 —— MAC 地址, 就是数据包的物理发送地址和物理接收地址;网络层:网络层的作用是引进一套新的地址, 使得能够区分不同的计算机是否属于同一个子网络; 这套地址就叫做网络地址(IP地址);网络地址帮助我们确定计算机所在的子网络, MAC 地址则将数据包送到该子网络中的目标网卡; 网络层协议包含的主要信息是源IP和目的IP;于是, 网络层出现以后, 每台计算机有了两种地址: 一种是 MAC 地址, 另一种是IP地址; 两种地址之间没有任何联系, MAC 地址是绑定网卡上的,网络地址则是管理员分配的,它们只是随机组合在一起。网络地址帮助我们确定计算机所在的子网络,MAC 地址则将数据包送到该子网络中的目标网卡。因此,从逻辑上可以推断,必定是先处理网络地址,然后再处理 MAC 地址。传输层:当我们一边聊QQ,一边聊微信,当一个数据包从互联网上发来的时候,我们怎么知道,它是来自QQ的内容,还是来自微信的内容?也就是说,我们还需要一个参数,表示这个数据包到底供哪个程序(进程)使用。这个参数就叫做“端口”(port),它其实是每一个使用网卡的程序的编号。每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。端口特点:对于同一个端口,在不同系统中对应着不同的进程对于同一个系统,一个端口只能被一个进程拥有应用层:应用程序收到“传输层”的数据,接下来就要进行解读。由于互联网是开放架构,数据来源五花八门,必须事先规定好格式,否则根本无法解读。“应用层”的作用,就是规定应用程序的数据格式2.3 通信过程两台计算机通过TCP/IP协议通讯的过程如下所示:2.4 总结通信过程:mac地址(不需要用户指定) --> (ARP 协议)Ip ——> macIP 地址(需要用户指定) ——> 确定主机port 端口号(需要用户指定) ——> 确定程序不能使用系统占用的默认端口; 建议使用5000+ 端口;65535为端口上限;二、Socket编程:1.什么是Socket:Socket, 英文含义是插座、插孔, 一般称之为套接字, 用于描述IP地址和端口; 可以实现不同程序间的数据通信;Socket起源于Unix, 而Unix基本哲学之一就是“一切皆文件”, 都可以用“打开open –> 读写write/read –> 关闭close”模式来操作;Socket就是该模式的一个实现, 网络的Socket数据传输是一种特殊的I/O, Socket也是一种文件描述符; Socket也具有一个类似于打开文件的函数调用: Socket(), 该函数返回一个整型的Socket描述符, 随后的连接建立、数据传输等操作都是通过该Socket实现的;在TCP/IP协议中, "IP地址+TCP或UDP端口号"唯一标识网络通讯中的一个进程; "IP地址+端口号"就对应一个socket; 欲建立连接的两个进程各自有一个socket来标识, 那么这两个socket组成的socket pair就唯一标识一个连接; 因此可以用Socket来描述网络连接的一对一关系;常用的Socket类型有两种: 流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM);流式是一种面向连接的Socket, 针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket, 对应于无连接的UDP服务应用;2. 网络应用程序设计模式:2.1 模式:C/S模式:传统的网络应用设计模式, 客户机(client)/服务器(server)模式; 需要在通讯两端各自部署客户机和服务器来完成数据通信;B/S模式:浏览器(Browser)/服务器(Server)模式; 只需在一端部署服务器, 而另外一端使用每台PC都默认配置的浏览器即可完成数据的传输;优缺点:对于C/S模式来说, 其优点明显;客户端位于目标主机上可以保证性能, 将数据缓存至客户端本地, 从而提高数据传输效率;一般来说客户端和服务器程序由一个开发团队创作, 所以他们之间所采用的协议相对灵活;可以在标准协议的基础上根据需求裁剪及定制; 例如, 腾讯所采用的通信协议,即为ftp协议的修改剪裁版;因此, 传统的网络应用程序及较大型的网络应用程序都首选C/S模式进行开发; 如, 知名的网络游戏魔兽世界; 3D画面, 数据量庞大, 使用C/S模式可以提前在本地进行大量数据的缓存处理, 从而提高观感;C/S模式的缺点也较突出:由于客户端和服务器都需要有一个开发团队来完成开发;工作量将成倍提升, 开发周期较长;从用户角度出发, 需要将客户端安插至用户主机上, 对用户主机的安全性构成威胁;这也是很多用户不愿使用C/S模式应用程序的重要原因;B/S模式相比C/S模式而言, 由于它没有独立的客户端, 使用标准浏览器作为客户端, 其工作开发量较小; 只需开发服务器端即可; 另外由于其采用浏览器显示数据, 因此移植性非常好, 不受平台限制; 如早期的偷菜游戏, 在各个平台上都可以完美运行;B/S模式的缺点也较明显:由于使用第三方浏览器, 因此网络应用支持受限;另外, 没有客户端放到对方主机上, 缓存数据不尽如人意, 从而传输数据量受到限制; 应用的观感大打折扣;第三, 必须与浏览器一样, 采用标准http协议进行通信, 协议选择不灵活;因此在开发过程中, 模式的选择由上述各自的特点决定; 根据实际需求选择应用程序设计模式;2.2 TCP的C/S架构:2.3 简单的C/S模型通信:a.Server端:Listen函数:func Listen(network, address string) (Listener, error)一键获取完整项目代码go1network: 选用的协议: TCP、UDP, 如:“tcp”或 “udp”;address: IP地址+端口号,如: “127.0.0.1:8000”或 “:8000”;Listener 接口:type Listener interface { Accept() (Conn, error) Close() error Addr() Addr}一键获取完整项目代码go12345Conn 接口:type Conn interface { Read(b []byte) (n int, err error) Write(b []byte) (n int, err error) Close() error LocalAddr() Addr RemoteAddr() Addr SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error}一键获取完整项目代码go12345678910参看 https://studygolang.com/pkgdoc 中文帮助文档中的demo:TCP-CS服务器:创建监听socket: listener := net.Listen("TCP", "IP+port") => IP+port --服务器自己的IP 和 port;启动监听 conn := listener.Accept(): conn用于 通信的 socket;conn.Read();处理使用 数据;返回数据: conn.Write();关闭listener、conn;TCP_Server.gopackage mainimport ( "fmt" "net")func main() { // 指定服务器 listener, err := net.Listen("tcp", "0.0.0.0:9000") if err != nil { fmt.Println("net.Listen err: ", err) return } defer listener.Close() fmt.Println("服务器等待客户端建立连接...") // 阻塞监听客户端请求 conn, err := listener.Accept() if err != nil { fmt.Println("listener.Accept err: ", err) return } defer conn.Close() buf := make([]byte, 4096) n, err := conn.Read(buf) if err != nil { fmt.Println("conn.Read err: ", err) return } // 打印数据 fmt.Println("服务器读取到: ", string(buf[:n])) // 回复数据 if _, err := conn.Write([]byte("server is ok")); err != nil { fmt.Println("conn.Write err: ", err) }}一键获取完整项目代码go123456789101112131415161718192021222324252627282930313233343536373839在整个通信过程中, 服务器端有两个socket参与进来, 但用于通信的只有 conn 这个socket; 它是由 listener创建的; 隶属于服务器端b.Client 端:Dial函数:
最新发布
11-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值