• golang网络通信超时设置


    网络通信中,为了防止长时间无响应的情况,经常会用到网络连接超时、读写超时的设置。

    本文结合例子简介golang的连接超时和读写超时设置。

    1.超时设置

    1.1 连接超时

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

    第三个参数timeout可以用来设置连接超时设置。
    如果超过timeout的指定的时间,连接没有完成,会返回超时错误。

    1.2 读写超时

    Conn定义中,包括读写的超时时间设置。

    type Conn interface {
    	// SetDeadline sets the read and write deadlines associated
    	// with the connection. It is equivalent to calling both
    	// SetReadDeadline and SetWriteDeadline.
    	//
    	... ...
    	SetDeadline(t time.Time) error
    
    	// SetReadDeadline sets the deadline for future Read calls
    	// and any currently-blocked Read call.
    	// A zero value for t means Read will not time out.
    	SetReadDeadline(t time.Time) error
    
    	// SetWriteDeadline sets the deadline for future Write calls
    	// and any currently-blocked Write call.
    	// Even if write times out, it may return n > 0, indicating that
    	// some of the data was successfully written.
    	// A zero value for t means Write will not time out.
    	SetWriteDeadline(t time.Time) error
    }
    

    通过上面的函数说明,可以得知,这里的参数t是一个未来的时间点,所以每次读或写之前,都要调用SetXXX重新设置超时时间,

    如果只设置一次,就会出现总是超时的问题。

    2.例子

    2.1 server

    server端监听连接,如果收到连接请求,就是创建一个goroutine负责这个连接的数据收发。

    为了测试超时,我们在写操作之前,sleep 3s。

    package main
    
    import (
            "net"
            "log"
            "time"
    )
    
    func main() {
            addr := "0.0.0.0:8080"
    
            tcpAddr, err := net.ResolveTCPAddr("tcp",addr)
    
            if err != nil {
                    log.Fatalf("net.ResovleTCPAddr fail:%s", addr)
            }
    
            listener, err := net.ListenTCP("tcp", tcpAddr)
            if err != nil {
                    log.Fatalf("listen %s fail: %s", addr, err)
            } else {
                    log.Println("listening", addr)
            }
    
    
            for {
                    conn, err := listener.Accept()
                    if err != nil {
                            log.Println("listener.Accept error:", err)
                            continue
                    }
    
                    go handleConnection(conn)
            }
    
    }
    
    
    func handleConnection(conn net.Conn) {
            defer conn.Close()
    
            var buffer []byte = []byte("You are welcome. I'm server.")
    
    
            for {
                    time.Sleep(3*time.Second)// sleep 3s
                    n, err := conn.Write(buffer)
                    if err != nil {
                            log.Println("Write error:", err)
                            break
                    }
                    log.Println("send:", n)
            }
    
            log.Println("connetion end")
    
    }
    

    2.2 client

    client建立连接时,使用的超时时间是3s。

    创建连接成功后,设置连接的读超时。
    每次读之前,都重新设置超时时间。

    package main
    
    import (
            "log"
            "net"
            "os"
            "time"
    )
    
    func main() {
            connTimeout := 3*time.Second
            conn, err := net.DialTimeout("tcp", "127.0.0.1:8080", connTimeout)  // 3s timeout
            if err != nil {
                    log.Println("dial failed:", err)
                    os.Exit(1)
            }
            defer conn.Close()
    
            readTimeout := 2*time.Second
    
            buffer := make([]byte, 512)
    
            for {
                    err = conn.SetReadDeadline(time.Now().Add(readTimeout)) // timeout
                    if err != nil {
                            log.Println("setReadDeadline failed:", err)
                    }
    
                    n, err := conn.Read(buffer)
                    if err != nil {
                            log.Println("Read failed:", err)
                            //break
                    }
    
                    log.Println("count:", n, "msg:", string(buffer))
            }
      
    }
    

    输出结果

    2019/05/12 16:18:19 Read failed: read tcp 127.0.0.1:51718->127.0.0.1:8080: i/o timeout
    2019/05/12 16:18:19 count: 0 msg:
    2019/05/12 16:18:20 count: 28 msg: You are welcome. I'm server.
    2019/05/12 16:18:22 Read failed: read tcp 127.0.0.1:51718->127.0.0.1:8080: i/o timeout
    2019/05/12 16:18:22 count: 0 msg: You are welcome. I'm server.
    2019/05/12 16:18:23 count: 28 msg: You are welcome. I'm server.
    2019/05/12 16:18:25 Read failed: read tcp 127.0.0.1:51718->127.0.0.1:8080: i/o timeout
    2019/05/12 16:18:25 count: 0 msg: You are welcome. I'm server.
    2019/05/12 16:18:26 count: 28 msg: You are welcome. I'm server.
    
  • 相关阅读:
    runtime 01-类与对象
    iOS 远程推送的实现
    iOS 选取上传图片界面
    NSAssert
    TableView下拉cell
    此博客主人已搬家访问新家地址:http://write.blog.csdn.net/postlist
    教你如何快速集成第3方
    iPhone应用开发 UITableView学习点滴详解
    苹果Xcode 证书生成、设置、应用完整图文教程
    NSXMLParser解析xml格式
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/10852755.html
Copyright © 2020-2023  润新知