Go語言DialTCP():網路通訊

2020-07-16 10:05:19
實際上,在前面《Dial()函數》一節中介紹的 Dial() 函數其實是對 DialTCP()、DialUDP()、DialIP() 和 DialUnix() 的封裝。我們也可以直接呼叫這些函數,它們的功能是一致的。這些函數的原型如下:

func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error)
func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error)
func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error)
func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error)

之前基於 TCP 傳送的 HTTP 請求,讀取伺服器資訊並返回 HTTP Head 的範例程式也可以使用下面的方式實現:
package main
import (
    "net"
    "os"
    "fmt"
    "io/ioutil"
)
func main() {
    if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])
        os.Exit(1)
    }
    service := os.Args[1]
    tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
    checkError(err)
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    checkError(err)
    _, err = conn.Write([]byte("HEAD / HTTP/1.0rnrn"))
    checkError(err)
    result, err := ioutil.ReadAll(conn)
    checkError(err)
    fmt.Println(string(result))
    os.Exit(0)
}
func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
}
與之前使用 Dail() 的例子相比,有兩個不同點:
  • net.ResolveTCPAddr() 用於解析地址和埠號;
  • net.DialTCP() 用於建立連結。

提示:這兩個函數在 Dial() 函數中都得到了封裝。

執行結果如下:

go run main.go baidu.com:80
HTTP/1.1 200 OK
Date: Fri, 03 Jan 2020 01:17:50 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-47cf7e6ee8400"
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Sat, 04 Jan 2020 01:17:50 GMT
Connection: Close
Content-Type: text/html

此外,net 包中還包含了一系列的工具函數,合理地使用這些函數可以更好地保障程式的品質。

驗證 IP 地址有效性的函數如下:

func net.ParseIP()

建立子網掩碼的函數如下:

func IPv4Mask(a, b, c, d byte) IPMask

獲取預設子網掩碼的函數如下:

func (ip IP) DefaultMask() IPMask

根據域名查詢 IP 的函數如下:

func ResolveIPAddr(net, addr string) (*IPAddr, error)
func LookupHost(name string) (cname string, addrs []string, err error)