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地址
什么是IP地址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地址(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的方法。
通过http://myexternalip.com/raw获取公网IPtype Listener interface {
Accept() (c Conn, err error)//等待并返回下一个连接到该连接的连接
Close() error //关闭listener,关闭后,任何阻塞accept的 *** 作都不再阻塞,并且返回error
Addr() Addr //返回该接口的网络地址
}
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
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)