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接口在网络上进行发送数据包.所以是跨平台的
  • 相关阅读:
    c# proto文件导入报错 File not found. Import "common.proto" was not found or had errors.
    拓端tecdat|Python用稀疏、高斯随机投影和主成分分析PCA对MNIST手写数字数据进行降维可视化
    拓端tecdat|上海无印良品地理空间分布特征与选址策略可视化研究
    拓端tecdat|Python用Keras神经网络序列模型回归拟合预测、准确度检查和结果可视化
    拓端tecdat|R语言分布滞后非线性模型(DLNM)空气污染研究温度对死亡率影响建模应用
    拓端tecdat|R语言用AR,MA,ARIMA 模型进行时间序列预测
    拓端tecdat|R语言广义二次跳跃、非线性跳跃扩散过程转移函数密度的估计及其应用
    拓端tecdat|Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析
    拓端tecdat|基于机器学习的印度肝脏病诊断分析
    拓端tecdat|R语言Metropolis Hastings采样和贝叶斯泊松回归Poisson模型
  • 原文地址:https://www.cnblogs.com/zhepama/p/3028508.html
Copyright © 2011-2022 走看看