net包之dial拨号和listen监听

今为止我们已经区分TCP和UDP API的不同,使用例子DialTCP和DialUDP分别返回一个TCPConn和 UDPConn。Conn类型是一个接口,TCPConn和UDPConn实现了该接口。在很大程度上,你可以通过该接口处理而不是用这两种类型。

Dialnetwork, address string) Conn, error)

net可以是”tcp”, “tcp4” IPv4-only), “tcp6” IPv6-only), “udp”, “udp4” IPv4-only), “udp6” IPv6-only), “ip”, “ip4″ IPv4-only)和”ip6” IPv6-only)任何一种。它将返回一个实现了Conn接口的类型。注意此函数接受一个字符串而不是raddr地址参数,因此,使用此程序可避免的地址类型。

使用该函数需要对程序轻微的调整。例如, 前面的程序从一个Web页面获取HEAD信息可以被重新写为

一个客户端的例子

package main

import 
        "bytes"
        "fmt"
        "io"
        "net"
        "os"
)

func main) {
        if lenos.Args) != 2 {
                fmt.Fprintfos.Stderr, "Usage: %s host:port", os.Args[0])
                os.Exit1)
        }
        service := os.Args[1]

        conn, err := net.Dial"tcp", service)
        checkErrorerr)

        _, err = conn.Write[]byte"HEAD / HTTP/1.0\r\n\r\n"))
        checkErrorerr)

        result, err := readFullyconn)
        checkErrorerr)

        fmt.Printlnstringresult))

        os.Exit0)
}

func checkErrorerr error) {
        if err != nil {
                fmt.Fprintfos.Stderr, "Fatal error: %s", err.Error))
                os.Exit1)
        }
}

func readFullyconn net.Conn) []byte, error) {
        defer conn.Close)

        result := bytes.NewBuffernil)
        var buf [512]byte
        for {
                n, err := conn.Readbuf[0:])
                result.Writebuf[0:n])
                if err != nil {
                        if err == io.EOF {
                                break
                        }
                        return nil, err
                }
        }
        return result.Bytes), nil
}

Listennet, laddr string) Listener, error)

返回一个实现Listener接口的对象.net参数可以为”tcp”, “tcp4”, “tcp6”, “unix” 或者 “unixpacket”.

func Listennet, laddr string) Listener, error) {
	la, err := resolveAddr"listen", net, laddr, noDeadline)
	if err != nil {
		return nil, err
	}
	switch la := la.type) {
	case *TCPAddr:
		return ListenTCPnet, la)    //监听TCP
	case *UnixAddr:
		return ListenUnixnet, la)   //监听Unix
	}
	return nil, UnknownNetworkErrornet)
}

看个服务端的例子

package main

import 
        "fmt"
        "net"
        "os"
)

func main) {

        service := ":1200"
        listener, err := net.Listen"tcp", service)
        checkErrorerr)

        for {
                conn, err := listener.Accept)
                if err != nil {
                        continue
                }
                go handleClientconn)
        }
}

func handleClientconn net.Conn) {
        defer conn.Close)

        var buf [512]byte
        for {
                n, err := conn.Readbuf[0:])
                if err != nil {
                        return
                }
                _, err2 := conn.Writebuf[0:n])
                if err2 != nil {
                        return
                }
        }
}

func checkErrorerr error) {
        if err != nil {
                fmt.Fprintfos.Stderr, "Fatal error: %s", err.Error))
                os.Exit1)
        }
}

ListenPacketnet, laddr string) PacketConn, error)

如果你想写一个UDP服务器, 有一个PacketConn的接口,和实现了该接口的方法ListenPacket.这里net参数为:udp”, “udp4”, “udp6”, “ip”, “ip4”, “ip6″或者”unixgram”

func ListenPacketnet, laddr string) PacketConn, error) {
	la, err := resolveAddr"listen", net, laddr, noDeadline)
	if err != nil {
		return nil, err
	}
	switch la := la.type) {
	case *UDPAddr:
		return ListenUDPnet, la)
	case *IPAddr:
		return ListenIPnet, la)
	case *UnixAddr:
		return ListenUnixgramnet, la)
	}
	return nil, UnknownNetworkErrornet)
}

Dialer

type Dialer struct {
	Timeout time.Duration
	Deadline time.Time
	LocalAddr Addr
}

DialTimeoutnetwork, address string, timeout time.Duration) Conn, error)

设置deadline,为time.Now).Addd.Timeout)

关于如何在网络上发送数据

很显然net包.提供了基本上的建立客户端与服务端的函数

这些函数会建立一个conn或者监听器,同时每个分别都拥有netFD类型参数
netFD类型抽象了各个平台,对网络的操作
netFD通过各个操作系统特有的socket接口在网络上进行发送数据包.所以是跨平台的

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注