网络地址

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)