在 go 中提供过了 net 包,net 包提供了对网络的支持。
net 包提供了对 socket 编程的支持,socket 编程分服务端和客户端编程,针对服务端可使用函数 Listen 创建监听服务,对于客户端可使用函数 Dial 连接服务器
1.1 net 包常用函数
常用函数
-
Listen: 用于创建监听服务器
-
ListenPacket:用于创建服务器端连接
-
Dial:用于创建与服务器连接
-
JoinHostPort:连接地址和端口
-
SplitHostort:分割地址和端口
-
LookupAddr:查找地址对应主机名
-
LookupHost: 根据主机名查看地址
-
ParseCIDR:解析 CIDR 格式 IP
1.1.1 JoinHostPort() 连接地址和端口
JoinHostPort:连接地址和端口
func net.JoinHostPort(host string, port string) string
将主机和端口组合成“host:port”形式的网络地址。
package main
import (
"fmt"
"net"
)
func main() {
fmt.Println(net.JoinHostPort("127.0.0.1", "8080"))
}
执行
[16:52:20 root@go codes]#go run net.go
127.0.0.1:8080
1.1.2 SplitHostPort() 分割地址和端口
SplitHostort:分割地址和端口
func net.SplitHostPort(hostport string) (host string, port string, err error)
网络地址拆分为主机IP 和 主机 Port
正确格式:
package main
import (
"fmt"
"net"
)
func main() {
fmt.Println(net.SplitHostPort("127.0.0.1:8080"))
}
执行
[16:59:28 root@go codes]#go run net.go
127.0.0.1 8080 <nil>
假如说我们输入的是一个错误的格式
package main
import (
"fmt"
"net"
)
func main() {
// 这里我们将 ip:port 的格式写成 ip-port 是一个错误格式
fmt.Println(net.SplitHostPort("127.0.0.1-8080"))
}
执行
[17:01:08 root@go codes]#go run net.go
address 127.0.0.1-8080: missing port in address
# 地址127.0.0.1-8080:地址中缺少端口
1.1.3 LookupAddr() 查找地址对应主机名
LookupAddr:查找地址对应主机名
func net.LookupAddr(addr string) (names []string, err error)
// addr 是查地址的
// 返回的是一个主机名的切片和 err 信息
很多时候我们需要通过 ip 来找他的主机名,或者说通过 主机名 来找它的 ip ,这个过程其实就类似于 DNS 的过程,对给定地址执行反向查找,返回映射到该地址的名称列表。
正确范例:
package main
import (
"fmt"
"net"
)
func main() {
fmt.Println(net.LookupAddr("127.0.0.1"))
}
执行
[17:01:33 root@go codes]#go run net.go
[localhost localhost.localdomain. localhost4 localhost4.localdomain4.] <nil>
# [localhost localhost.localdomain. localhost4 localhost4.localdomain4.] 返回的是主机头名称
[17:12:50 root@go codes]#cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
错误范例:
package main
import (
"fmt"
"net"
)
func main() {
// 这里写一个不存在的 ip
fmt.Println(net.LookupAddr("220.181.38.148"))
}
执行
[17:26:40 root@go codes]#go run net.go
[] lookup 79.69.156.39.in-addr.arpa. on 114.114.114.114:53: no such host
# []查找148.38.181.220.in-addr.arpa。114.114.114.114:53:没有这样的主持人
1.1.4 LookupHost() 根据主机名查看地址
LookupHost: 根据主机名查看地址
func net.LookupHost(host string) (addrs []string, err error)
使用本地解析程序查找给定的主机。它返回该主机地址的一部分。
package main
import (
"fmt"
"net"
)
func main() {
// 查询百度
fmt.Println(net.LookupHost("www.baidu.com"))
// 查询本地
fmt.Println(net.LookupHost("localhost"))
}
执行
[17:27:37 root@go codes]#go run net.go
[110.242.68.3 110.242.68.4] <nil>
[127.0.0.1 ::1] <nil>
# 返回的就是一个地址列表和 error ,这个就是通过 DNS 解析
1.1.5 ParseIP() 判断是否为正确的 ip
ParseIP:判断是否为正确的 ip
func net.ParseIP(s string) net.IP
范例
package main
import (
"fmt"
"net"
)
func main() {
for _, ipStr := range []string{"127.0.0.1", "::1", "xxxx"} {
ip := net.ParseIP(ipStr)
fmt.Println(ip)
}
}
执行
[17:42:01 root@go codes]#go run net.go
127.0.0.1
::1
<nil> # 由于 xxxx 不是一个正确的 ip 地址所以返回值为 nil
1.1.6 ParseCIDR() 查看子网掩码
func net.ParseCIDR(s string) (net.IP, *net.IPNet, error)
查看子网掩码
package main
import (
"fmt"
"net"
)
func main() {
// 这里传入的是一个 192.168.1.1/24 的 24 位子网掩码
ip, ipnet, err := net.ParseCIDR("192.168.1.1/24")
fmt.Println(ip, ipnet, err)
}
执行
[17:47:19 root@go codes]#go run net.go
192.168.1.1 192.168.1.0/24 <nil>
# 192.168.1.1 ip 地址
# 192.168.1.0/24 子网掩码
# <nil> 错误为空
1.1.6.1 Contains() 方法查询该网段是否包含地址 ip
Contains() 方法是 net.ParseCIDR 函数中返回的一个 IPNet 结构体中的方法
Contains() 方法是用来报告该网段是否包含地址 ip
func (*net.IPNet).Contains(ip net.IP) bool
// Contains(ip net.IP) 传递 ip 格式
package main
import (
"fmt"
"net"
)
func main() {
// 这里写的是 192.168.1.1/24 网段
ip, ipnet, err := net.ParseCIDR("192.168.1.1/24")
fmt.Println(ip, ipnet, err)
// 由于是 24 位子网掩码,而这里写的是 192.168.0.1 他的第 16 位是 0 所以结果为 false
fmt.Println(ipnet.Contains(net.ParseIP("192.168.0.1")))
}
执行
[18:09:23 root@go codes]#go run net.go
192.168.1.1 192.168.1.0/24 <nil>
false
# false 由于 192.168.1.1/24 24位子网 不包含 192.168.0.1 地址
1.1.7 InterfaceAddrs() 返回系统的所有 ip
func net.InterfaceAddrs() ([]net.Addr, error)
InterfaceAddrs
返回系统的单播接口地址列表。
package main
import (
"fmt"
"net"
)
func main() {
addr, err := net.InterfaceAddrs()
fmt.Println(addr, err)
}
执行
[18:09:26 root@go codes]#go run net.go
[127.0.0.1/8 10.0.0.10/24 192.168.122.1/24] <nil>
# 127.0.0.1/8 10.0.0.10/24 192.168.122.1/24 本机网卡所有存在的 ip
# <nil> 返回值为空
1.1.8 Interfaces() 获取网卡信息
接口返回系统网络接口的列表比如 mac 地址。
func net.Interfaces() ([]net.Interface, error)
// 返回 []net.Interface 网卡接口信息切片
package main
import (
"fmt"
"net"
)
func main() {
intfs, _ := net.Interfaces()
// 遍历 intfs 网卡信息切片,输出值
for _, netinfo := range intfs {
fmt.Println(netinfo.Index, netinfo.MTU, netinfo.HardwareAddr,netinfo.Name, netinfo.Flags)
// 获取当前该网卡地址 ip
fmt.Println(netinfo.Addrs())
}
}
执行
[18:33:20 root@go codes]#go run net.go
1 65536 lo up|loopback
[127.0.0.1/8] <nil>
2 1500 00:0c:29:93:c6:1b eth0 up|broadcast|multicast
[10.0.0.10/24] <nil>
3 1500 52:54:00:ff:d5:b5 virbr0 up|broadcast|multicast
[192.168.122.1/24] <nil>
4 1500 52:54:00:ff:d5:b5 virbr0-nic broadcast|multicast
[] <nil>
# 1 lo 回环网卡信息
# 2 eth0 网卡信息
# 3 virbr0 网卡信息
# 4 virbr0-nic 网卡信息