zoukankan      html  css  js  c++  java
  • 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接口在网络上进行发送数据包.所以是跨平台的
  • 相关阅读:
    MapServer Tutorial——MapServer7.2.1教程学习——第一节:MapServer的基本配置管理,静态地图应用以及MapFile文件
    MapServer Tutorial——MapServer7.2.1教程学习——教程背景
    MapServer Tutorial——MapServer7.2.1教程学习(大纲)
    MapServer Configuring with IIS
    GDAL源码编译(32位)
    开机自启动相关程序
    异常:Invalid character found in the request target. The valid characters are defined in RFC 3986
    如何将解压版的tomcat设置为windows 服务启动
    修改Tomcat控制台标题
    Tomcat控制台中文乱码解决办法
  • 原文地址:https://www.cnblogs.com/zhepama/p/3028508.html
Copyright © 2011-2022 走看看