golang中net包用法

golang中net包用法,第1张

net包提供了可移植的网络I/O接口,包括TCP/IP、UDP、域名解析和Unix域socket.

虽然本包提供了对网络原语的访问,但大多数使用者只需要Dial、Listen和Accpet函数的基本接口;以及Conn和Listener接口。crypto/tls包提供了相同的接口和类似的Dial和Listen函数。

常量

//表示ip地址的长度(bytes),其中ipv4的长度为4,ipv6为16

const (
    IPv4len = 4
    IPv6len = 16
)

常见的ipv4地址:

var (
    IPv4bcast     = IPv4(255, 255, 255, 255) // 广播地址
    IPv4allsys    = IPv4(224, 0, 0, 1)       // 所有系统,包括主机和路由器,这是一个组播地址
    IPv4allrouter = IPv4(224, 0, 0, 2)       // 所有组播路由器
    IPv4zero      = IPv4(0, 0, 0, 0)         // 本地网络,只能作为本地源地址其才是合法的

常见的IPV6地址

var (
    IPv6zero                   = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}     
    IPv6unspecified            = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    IPv6loopback               = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
    IPv6linklocalallnodes      = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
    IPv6linklocalallrouters    = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
)

什么是IP地址

IP地址(Internet Protocol Address,称互联网协议地址,简称IP Address),是一种给主机在Internet上进行编址的方式。常见的地址分IPV4和IPV6。

IPV4是由32位二进制数表示。用XXX.XXX.XXX.XXX表示。每组XXX小于或等于255的10进制数,IPV4地址总数为232,不过一些地址是为特殊用途所保留的,专用网络(约18百万)和多播地址(270百万)。其中IPV4分ABCDE五类地址。

A类地址

第一位为0,主要的是位

1.位1,第1字节为网络地址,其他3个字节为主机地址

2.地址范围: 1.0.0.1—126.255.255.254

3.10.X.X.X为私有地址,范围是10.0.0.0-10.255.255.255

4.127.X.X.X是保留地址,用做环回测试

B类地址

其两位为10,注意的是位。

1.第1和第2字节为网络地址,后2字节为主机地址。

2.地址范围: 128.0.0.1—191.255.255.254

3.私有地址范围: 172.16.0.0—172.31.255.255

4.保留地址:169.254.X.X

C类地址

前三位为110,注意的是位。

1.前3字节为网络地址,后字节为主机地址

2.地址范围:192.0.0.1—223.255.255.254

3.私有地址: 192.168.X.X,范围从192.168.0.0-192.168.255.255

D类地址

前四位为1110,注意3位。

1.不分网络地址和主机地址。

E类地址

前五位为11110。

1.不分网络地址和主机地址。

特殊地址

1、0.0.0.0只能做源地址

2、255.255.255.255是广播地址

3、127.x.x.x为环回地址,本机使用

专用地址

专用地址就是内网地址

10/8 地址范围:10.0.0.0——10.255.255.255,

172.16/12 地址范围:172.16.0.0——172.31.255.255,

192.168/16地址范围:192.168.0.0——192.168.255.255。

什么是内网

一些小型企业或者学校,通常都是申请一个固定的IP地址,然后通过IP共享(IP Sharing),使用整个公司或学校的机器都能够访问互联网。而这些企业或学校的机器使用的IP地址就是内网IP,内网IP是在规划IPv4协议时,考虑到IP地址资源可能不足,就专门为内部网设计私有IP地址(或称之为保留地址)。一般常用内网IP地址都是这种形式的:10.X.X.X、172.16.X.X-172.31.X.X、192.168.X.X等。需要注意的是,内网的计算机可向Internet上的其他计算机发送连接请求,但Internet上其他的计算机无法向内网的计算机发送连接请求。我们平时可能在内网机器上搭建过网站或者FTP服务器,而在外网是不能访问该网站和FTP服务器的,原因就在于此。

什么是公网IP

公网IP就是除了保留IP地址以外的IP地址,可以与Internet上的其他计算机随意互相访问。我们通常所说的IP地址,其实就是指的公网IP。互联网上的每台计算机都有一个独立的IP地址,该IP地址唯一确定互联网上的一台计算机。这里的IP地址就是指的公网IP地址。

怎样理解互联网上的每台计算机都有一个唯一的IP地址?

其实,互联网上的计算机是通过“公网IP+内网IP”来唯一确定的。就像很多大楼都是201房间一样,房间号可能一样,但是大楼肯定是唯一的。公网IP地址和内网IP地址也是同样,不同企业或学校的机器可能有相同的内网IP地址,但是他们的公网IP地址肯定不同。那么这些企业或学校的计算机是怎样进行IP地址共享的呢?这就需要使用NAT(Network Address Translation,网络地址转换)功能。当内部计算机要连接互联网时,首先需要通过NAT技术,将内部计算机数据包中有关IP地址的设置都设成NAT主机的公共IP地址;然后再传送到Internet,虽然内部计算机使用的是私有IP地址,但在连接Internet时,就可以通过NAT主机的NAT技术,将内网IP地址修改为公网IP地址,如此一来,内网计算机就可以向Internet请求数据了。

包详解

type Error //表示网络错误

type Error interface {
    error      //错误
    Timeout() bool   // Is the error a timeout? 该错误是时间超时错误吗?
    Temporary() bool // Is the error temporary? 这个错误是一个临时错误吗?
}

type AddrError //网络地址错误

type AddrError struct {
    Err  string  //错误
    Addr string //地址字符串表示
}

func (e *AddrError) Error() string          //错误
func (e *AddrError) Temporary() bool   //该错误是否是一个临时错误
func (e *AddrError) Timeout() bool       //该错误是否是超时错误

type DNSConfigError //DNS配置错误,表示在读取机器DNS配置过程中的出现的错误

type DNSConfigError struct {
    Err error
}

func (e *DNSError) Error() string
func (e *DNSError) Temporary() bool
func (e *DNSError) Timeout() bool

type InvaildAddrError //无效地址错误

type InvalidAddrError string

func (e InvalidAddrError) Error() string
func (e InvalidAddrError) Temporary() bool
func (e InvalidAddrError) Timeout() bool

type ParseError //解析错误,ParseError表示一个格式错误的字符串,其中Type表示期待的格式

type ParseError struct {
    Type string
    Text string
}

func (e *ParseError) Error() string    //将错误表示为字符串形式

type UnknownNetworkError //未知网络错误

type UnknownNetworkError string
func (e UnknownNetworkError) Error() string
func (e UnknownNetworkError) Temporary() bool
func (e UnknownNetworkError) Timeout() bool

//网络终端地址

type Addr interface {
    Network() string // 网络名称
    String() string  // 地址字符串表示
}

//conn是一个通用的面向流的网络连接,多个goroutine可以调用conn中的方法

type Conn interface {
    // Read从连接中读取数据,Read方法会在超过某个固定时间限制后返回一个表示超时的错误,该错误的TImeout()==True
    Read(b []byte) (n int, err error)
    // Write向conn中写入数据,与Read类似, Write方法也会在超过某个固定时间后返回超时错误,该错误的Timeout()==True
    Write(b []byte) (n int, err error)
    // Close方法关闭该连接,同时任何阻塞的Read或Write方法将不再阻塞,并且返回错误。
    Close() error
    // 返回本地网络地址
    LocalAddr() Addr
    // 返回远端网络地址
    RemoteAddr() Addr
    // 设定连接的读写deadline,它等价于调用SetReadDeadline和SetWriteDeadline进行conn连接的读写deadline设定。其中deadline是一个绝对时间,
        //在deadline时间之后,任何的读写 *** 作都不再阻塞,而是直接失败,deadline对之后的所有I/O *** 作都起效,而不仅仅是下一次的读或写 *** 作,
    // :一:空闲超时,这种方法实现其中有两类超时比较特殊是在每次成功读或者写 *** 作后都延长超时期限,当没有读写 *** 作空闲时便会超时;二:参数t为零值表示不设置
        //超时期限,即不会超时timeout
    SetDeadline(t time.Time) error
    // 设定连接的读 *** 作deadline,参数t为零值表示不设置期限
    SetReadDeadline(t time.Time) error
    // 设定连接的写 *** 作deadline,参数t为零值表示不设置期限
    // 即使写超时,也有可能出现写入字数n>0,说明成功写入了部分数据,但是没有将数据全部写入。
    SetWriteDeadline(t time.Time) error
}

//Dial连接到指定address和name的网络,其中network包含如下几种:"tcp", "tcp4" (IPv4-only), //"tcp6" (IPv6-only),"udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"(IPv4-only), "ip6" //(IPv6-only), "unix", "unixgram" and"unixpacket". 对于TCP和UDP网络来说,addresses的形式    //如下host:port,其行使和JoinHostPort以及SplitHostPort函数中的addresses形式一致。举例如下所示:

Dial("tcp", "12.34.56.78:80")
Dial("tcp", "google.com:http")
Dial("tcp", "[2001:db8::1]:http")
Dial("tcp", "[fe80::1%lo0]:80")

func Dial(network, address string) (Conn, error)  

//该函数与Dial函数类似,但是多一个超时设置timeout,如果需要的话,timeout中包含域名解析

func DialTimeout(network, address string, timeout time.Duration) (Conn, error)

//包含连接到一个地址的选项,//在Dialer结构体中的每个参数的零值相当于没有那个值,因此调用

//零值的Dialer中的Dial函数相当于直接调用Dial函数

type Dialer struct {
    // Timeout是dial *** 作等待连接建立的最大时长,默认值代表没有超时。如果Deadline字段也被设置了,dial *** 作也可能更早失败。
    // 不管有没有设置超时, *** 作系统都可能强制执行它的超时设置。例如,TCP(系统)超时一般在3分钟左右。Timeout是一个相对时间,是时间段,而Deadline是一个绝
        //对时间,是时间点,这是二者的区别
    Timeout time.Duration
 
       // Deadline是一个具体的时间点期限,超过该期限后,dial *** 作就会失败。如果Timeout字段也被设置了,dial *** 作也可能更早失败。零值表示没有期限。
    Deadline time.Time
    
       // LocalAddr是dial一个地址时使用的本地地址。
    // 该地址必须是与dial的网络相容的类型。
    // 如果为nil,将会自动选择一个本地地址。
    LocalAddr Addr
 
        // 当网络类型是tcp并且一个主机名字具有多个dns记录地址时,DualStack允许一个dial创建多个ipv4和ipv6的连接,并且返回第一个创建的连接
    DualStack bool
 
        // KeepAlive指定一个网络连接的保持声明的时间段;如果为0,会禁止keep-alive。当网络协议不支持keep-alives时便会忽略掉这个值。
    // 不支持keep-alive的网络连接会忽略本字段。
    KeepAlive time.Duration
}

 //Listener是一个用于面向流的网络协议的公用的网络监听器接口。多个线程可能会同时调用一个Listener的方法。

type Listener interface {
    
    Accept() (c Conn, err error)//等待并返回下一个连接到该连接的连接
 
    Close() error   //关闭listener,关闭后,任何阻塞accept的 *** 作都不再阻塞,并且返回error
 
    Addr() Addr   //返回该接口的网络地址
}

通过http://myexternalip.com/raw获取公网IP
func getExternalIp() string {
    resp, err := http.Get("https://myexternalip.com/raw")
    if err != nil {
        return ""
    }
    defer resp.Body.Close()
    content, _ := ioutil.ReadAll(resp.Body)
    //buf := new(bytes.Buffer)
    //buf.ReadFrom(resp.Body)
    //s := buf.String()
    return string(content)
}
判断是否是公网IP
func IsPublicIP(IP net.IP) bool {
	if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {
		return false
	}
	if ip4 := IP.To4(); ip4 != nil {
		switch true {
		case ip4[0] == 10:
			return false
		case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
			return false
		case ip4[0] == 192 && ip4[1] == 168:
			return false
		default:
			return true
		}
	}
	return false
}
获取本地IP 通过net.InterfaceAddrs获取本地IP
func getLocalIPv4s() ([]string, error) {
	var ips []string
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return ips, err
	}
 
	for _, a := range addrs {
		// 检查ip地址判断是否回环地址
		if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() && ipNet.IP.To4() != nil {
			ips = append(ips, ipNet.IP.String())
		}
	}
 
	return ips, nil
}
通过端口名称获取本地IP
func GetIPv4ByInterface(name string) ([]string, error) {
	var ips []string
 
	netInterface, err := net.InterfaceByName(name)
	if err != nil {
		return nil, err
	}
	 mac物理地址
	//fmt.Println(netInterface.HardwareAddr.String())
 
	addrs, err := netInterface.Addrs()
	if err != nil {
		return nil, err
	}
 
	for _, a := range addrs {
		if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() && ipNet.IP.To4() != nil {
			ips = append(ips, ipNet.IP.String())
		}
	}
 
	return ips, nil
}
通过DNS服务器8.8.8.8:80获取本地IP
func GetLocalIP() string {
    conn, _ := net.Dial("udp", "8.8.8.8:80")
    defer conn.Close()
    localAddr := conn.LocalAddr().String()
    idx := strings.LastIndex(localAddr, ":")
    return localAddr[0:idx]
}
ip地址string和int转换 ip地址string转换int
func inet_aton(ipnr net.IP) int64 {
	bits := strings.Split(ipnr.String(), ".")
 
	b0, _ := strconv.Atoi(bits[0])
	b1, _ := strconv.Atoi(bits[1])
	b2, _ := strconv.Atoi(bits[2])
	b3, _ := strconv.Atoi(bits[3])
 
	var sum int64
 
	sum += int64(b0) << 24
	sum += int64(b1) << 16
	sum += int64(b2) << 8
	sum += int64(b3)
 
	return sum
}
ip地址int转换string
func inet_ntoa(ipnr int64) net.IP {
	var byteSlice [4]byte
	byteSlice[0] = byte(ipnr & 0xFF)
	byteSlice[1] = byte((ipnr >> 8) & 0xFF)
	byteSlice[2] = byte((ipnr >> 16) & 0xFF)
	byteSlice[3] = byte((ipnr >> 24) & 0xFF)
 
	return net.IPv4(byteSlice[3], byteSlice[2], byteSlice[1], byteSlice[0])
}
判断ip地址区间
func IpBetween(from net.IP, to net.IP, test net.IP) bool {
	if from == nil || to == nil || test == nil {
		fmt.Println("An ip input is nil") // or return an error!?
		return false
	}
 
	from16 := from.To16()
	to16 := to.To16()
	test16 := test.To16()
	if from16 == nil || to16 == nil || test16 == nil {
		fmt.Println("An ip did not convert to a 16 byte") // or return an error!?
		return false
	}
 
	if bytes.Compare(test16, from16) >= 0 && bytes.Compare(test16, to16) <= 0 {
		return true
	}
	return false
}
随机获取本地端口
func GetFreePort() (int, error) {
	addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
	if err != nil {
		return 0, err
	}
	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return 0, err
	}
	defer l.Close()
	return l.Addr().(*net.TCPAddr).Port, nil
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/990024.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存