net包之dial拨号和listen监听

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

Dial(network, 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 len(os.Args) != 2 {

                fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])

                os.Exit(1)

        }

        service := os.Args[1]



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

        checkError(err)



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

        checkError(err)



        result, err := readFully(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)

        }

}



func readFully(conn net.Conn) ([]byte, error) {

        defer conn.Close()



        result := bytes.NewBuffer(nil)

        var buf [512]byte

        for {

                n, err := conn.Read(buf[0:])

                result.Write(buf[0:n])

                if err != nil {

                        if err == io.EOF {

                                break

                        }

                        return nil, err

                }

        }

        return result.Bytes(), nil

}

Listen(net, laddr string) (Listener, error)

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

func Listen(net, laddr string) (Listener, error) {

	la, err := resolveAddr("listen", net, laddr, noDeadline)

	if err != nil {

		return nil, err

	}

	switch la := la.(type) {

	case *TCPAddr:

		return ListenTCP(net, la)    //监听TCP

	case *UnixAddr:

		return ListenUnix(net, la)   //监听Unix

	}

	return nil, UnknownNetworkError(net)

}

看个服务端的例子

package main



import (

        "fmt"

        "net"

        "os"

)



func main() {



        service := ":1200"

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

        checkError(err)



        for {

                conn, err := listener.Accept()

                if err != nil {

                        continue

                }

                go handleClient(conn)

        }

}



func handleClient(conn net.Conn) {

        defer conn.Close()



        var buf [512]byte

        for {

                n, err := conn.Read(buf[0:])

                if err != nil {

                        return

                }

                _, err2 := conn.Write(buf[0:n])

                if err2 != nil {

                        return

                }

        }

}



func checkError(err error) {

        if err != nil {

                fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())

                os.Exit(1)

        }

}



ListenPacket(net, laddr string) (PacketConn, error)

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

func ListenPacket(net, laddr string) (PacketConn, error) {

	la, err := resolveAddr("listen", net, laddr, noDeadline)

	if err != nil {

		return nil, err

	}

	switch la := la.(type) {

	case *UDPAddr:

		return ListenUDP(net, la)

	case *IPAddr:

		return ListenIP(net, la)

	case *UnixAddr:

		return ListenUnixgram(net, la)

	}

	return nil, UnknownNetworkError(net)

}

Dialer

type Dialer struct {

	Timeout time.Duration

	Deadline time.Time

	LocalAddr Addr

}

DialTimeout(network, address string, timeout time.Duration) (Conn, error)

设置deadline,为time.Now().Add(d.Timeout)

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

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

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

你可能感兴趣的:(list)