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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM