网络地址
IPv4 address
地址用一个32位的整数表示,通常在4个字节中用点"."分隔, 比如127.0.0.1 or 72.18.60.88.
任何设备的IP地址都是由两部分组成:设备所在的网络和在这个网络下的地址。
在A类网络中,第一个字节表示网络,后面三个用于标识设备。A类网络只有128种,所有者一般为早期的互联网玩家,比如IBM, General Electric Company and MIT
B类网络使用前两个字节标识网络,最后两个部分用于标识子网中的设备。允许每个子网络中有2^16(35,536)个设备
C类网络使用前三个字节用来标识网络,最后一部分用来标识设备,这就只允许每个子网络最多有2^8(实际为254, 而不是256)个设备
这中方案有时会行不通,比如400台电脑在一个网络中,254会大少,而65,536又太大了,在二进制算法中,你需要512(9 bit)。 这就需要使用到23位的网络和9 bit来表示设备地址。如果你需要表示1024个设备,那么你需要使用22位的网络,10bit来表示设备。
给定了一个设备的IP地址,并且知道它的网络使用了多少位(N), 那么就能简单的提取出它的网络地址和设备在这个网络中的地址。 这就是Network mask的意义。Network mask是一个32位的二制字数字,前N位为1,其它的为0。举例来说,如果16位用于网络地址,mask为11111111111111110000000000000000. 使用二进制有点不方便,我们可以使用16位的网络地址,它为255.255.0.0, 对于24的网络,mask为255.255.255.0, 23位的地址为255.255.254.0, 22bit 255.255.252.0.
如果要找到一个设备的所在的网络,可以使用IP地址 位操作(AND)它的子网掩码,而如果是要找一个设备在子网中的地址,则可以使用IP地址按位AND子网掩码的补集(对mask取反)
IPv6地址
互联网的增长远远超出当期的预期。 32位地址已经不够使用。也存在一些变通的方案,比如NAT地址,但最终我们还是需要切换到更宽的地址空间。 IPv6使用128位的地址。使用字节来表示IPv6的地址非常难以处理,所以使用16进制,每个4个字节一组(32bit),之前使用":"分割。 比如2002:c0e8:82e7:0:0:0:c0e8:82e7.
这些地址非常不好记忆,所以DNS变得非常重要。我们可以省略掉0和重复的数字,来精简地址,比如localhost 0:0:0:0:0:0:0:1 可以简写为::1
IP address type
The type IP
Golang的"net"包中定义了很多的类型,函数,和方法用于网络编程。以下是类型IP的定义
type IP []byte
在类型IP中有许多的方法,但在实践中只使用到少数部分。比如,函数ParseIP(String)接受一个带点的IPv4地址和冒号分割的IPv6地址,而IP类型的String方法返回一个字符串。注意你可能不会得到开始输入的值,比如0:0:0:0:0:0:0:1的字符串为::1.
package main
import (
"fmt"
"net"
"os"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: %s ip-addr\n", os.Args[0])
os.Exit(1)
}
name := os.Args[1]
addr := net.ParseIP(name)
if addr == nil {
fmt.Println("Invalid address")
} else {
fmt.Println("The address is ", addr.String())
}
os.Exit(0)
}
//IP 127.0.0.1
The address is 127.0.0.1
//IP 0:0:0:0:0:0:0:1
The address is ::1
The type IPmask
type IPMask []byte
创建一个4字节的子网掩码
func IPv4Mask(a, b, c, d byte) IPMask
或者使用IP类型的的方法返回一个默认的子网掩码
func (ip IP) DefaultMask() IPMask
需要注意的是IPMask String()返回的是16进制的数字,比如ffff0000表示255.255.0.0, 一个子网掩码之后可以用于查找一个IP的址址所在的网络
func (ip IP) Mask(mask IPMask) IP
以下是实际例子
mask := addr.DefaultMask()
network := addr.Mask(mask)
ones, bits := mask.Size()
fmt.Println("Address is ", addr.String(),
" Default mask length is ", bits,
"Leading ones count is ", ones,
"Mask is (hex) ", mask.String(),
" Network is ", network.String())
os.Exit(0)
/*
//Mask 127.0.0.1
Address is 127.0.0.1 Default mask length is 32 Leading ones count is 8 Mask is (hex) ff000000 Network is 127.0.0.0
*/
The type IPAddr
在net包中,很多函数和方法返回一个IPAddr类型的指针,它的结构如下
type IPAddr struct {
IP IP
Zone string // IPv6 scoped addressing zone
}
此类型最主要的一个用途是用于执行DNS查找IP
//net可以为"ip", "ip4", "ip6"
func ResolveIPAddr(net, addr string) (*IPAddr, os.Error)
name := os.Args[1]
addr, err := net.ResolveIPAddr("ip", name)
if err != nil {
fmt.Println("Resolution error", err.Error())
os.Exit(1)
}
fmt.Println("Resolved address is ", addr.String())
//ResolveIP www.google.com
//Resolved address is 66.102.11.104
Host lookup
函数ResolveIPAddr将根据域名查找IP, 并返回一个IP地址,可是主机可能会有多个IP地址,通常为多个网卡。所以它们可以有多个主机名字(域名), 作为别名
func LookupHost(host string) (addrs []string, err error)