【go語言 socket程式設計系列】IPAddr型別及ResolveIPAddr方法
阿新 • • 發佈:2018-12-11
【型別定義】
IPAddr型別本質上是一個IP型別,原始碼定義檔案:golang/src/pkg/net/iprawsock.go
常用方法會返回一個*IPAddr的資料。
package net
// IPAddr represents the address of an IP end point.
type IPAddr struct {
IP IP
Zone string // IPv6 scoped addressing zone
}
【net.ResolveIPAddr 方法】
func ResolveIPAddr(net, addr string) (*IPAddr, error)
將addr解析成ip,返回一個*IPAddr資料
net 引數為 "ip", "ip4" 或者為"ip6",net 為空這預設 ip
原始碼如下
// ResolveIPAddr parses addr as an IP address of the form "host" or // "ipv6-host%zone" and resolves the domain name on the network net, // which must be "ip", "ip4" or "ip6". func ResolveIPAddr(net, addr string) (*IPAddr, error) { if net == "" { // a hint wildcard for Go 1.0 undocumented behavior net = "ip" } afnet, _, err := parseNetwork(net) if err != nil { return nil, err } switch afnet { case "ip", "ip4", "ip6": default: return nil, UnknownNetworkError(net) } a, err := resolveInternetAddr(afnet, addr, noDeadline) if err != nil { return nil, err } return a.toAddr().(*IPAddr), nil }
主要呼叫到以下兩個函式
1、parseNetwork(net)
2、resolveInternetAddr(afnet, addr, noDeadline)
parseNetwork 函式定義如下,在dial.go檔案中。
會呼叫lookupProtocol(protostr)方法 從unix作業系統中的/etc/protocols檔案中查詢協議名詞,並返回相應的協議號
func parseNetwork(net string) (afnet string, proto int, err error) { i := last(net, ':') if i < 0 { // no colon switch net { case "tcp", "tcp4", "tcp6": case "udp", "udp4", "udp6": case "ip", "ip4", "ip6": case "unix", "unixgram", "unixpacket": default: return "", 0, UnknownNetworkError(net) } return net, 0, nil } afnet = net[:i] switch afnet { case "ip", "ip4", "ip6": protostr := net[i+1:] proto, i, ok := dtoi(protostr, 0) if !ok || i != len(protostr) { proto, err = lookupProtocol(protostr) if err != nil { return "", 0, err } } return afnet, proto, nil } return "", 0, UnknownNetworkError(net) }
resolveInternetAddr函式定義如下,在 ipsock.go檔案中
// resolveInternetAddr resolves addr that is either a literal IP
// address or a DNS name and returns an internet protocol family
// address. It returns a list that contains a pair of different
// address family addresses when addr is a DNS name and the name has
// mutiple address family records. The result contains at least one
// address when error is nil.
func resolveInternetAddr(net, addr string, deadline time.Time) (netaddr, error) {
var (
err error
host, port, zone string
portnum int
)
switch net {
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
if addr != "" {
if host, port, err = SplitHostPort(addr); err != nil {
return nil, err
}
if portnum, err = parsePort(net, port); err != nil {
return nil, err
}
}
case "ip", "ip4", "ip6":
if addr != "" {
host = addr
}
default:
return nil, UnknownNetworkError(net)
}
inetaddr := func(ip IP) netaddr {
switch net {
case "tcp", "tcp4", "tcp6":
return &TCPAddr{IP: ip, Port: portnum, Zone: zone}
case "udp", "udp4", "udp6":
return &UDPAddr{IP: ip, Port: portnum, Zone: zone}
case "ip", "ip4", "ip6":
return &IPAddr{IP: ip, Zone: zone}
default:
panic("unexpected network: " + net)
}
}
if host == "" {
return inetaddr(nil), nil
}
// Try as a literal IP address.
var ip IP
if ip = parseIPv4(host); ip != nil {
return inetaddr(ip), nil
}
if ip, zone = parseIPv6(host, true); ip != nil {
return inetaddr(ip), nil
}
// Try as a DNS name.
host, zone = splitHostZone(host)
ips, err := lookupIPDeadline(host, deadline)
if err != nil {
return nil, err
}
var filter func(IP) IP
if net != "" && net[len(net)-1] == '4' {
filter = ipv4only
}
if net != "" && net[len(net)-1] == '6' || zone != "" {
filter = ipv6only
}
return firstFavoriteAddr(filter, ips, inetaddr)
}
【程式碼實現】
package main
import (
"fmt"
"net"
"os"
)
func main() {
mydns := "www.csdn.net"
addr, err := net.ResolveIPAddr("ip", mydns)
checkError(err)
fmt.Println("dns is:", mydns)
fmt.Println("ip is:", addr.String())
}
func checkError(err error) {
if err != nil {
fmt.Println("Fatal err!", err.Error())
os.Exit(1)
}
}
編譯執行
$./l_ResolveIPAddr
dns is: www.csdn.net
ip is: 47.95.164.112
$