首页 > 其他分享 >【go】golang网络通信超时设置

【go】golang网络通信超时设置

时间:2022-10-17 10:24:29浏览次数:48  
标签:log err 18 golang 2019 time go 超时

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

本文结合例子简介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.

 

标签:log,err,18,golang,2019,time,go,超时
From: https://www.cnblogs.com/opensmarty/p/16798189.html

相关文章

  • go语言注释,标识符 | 17
    注释注释不会被编译,每一个包应该有相关注释。单行注释是最常见的注释形式,你可以在任何地方使用以//开头的单行注释。多行注释也叫块注释,均已以/*开头,并以*/结尾。如://......
  • 【Django-rest-framework框架】 第12回 simpleui 集成监控大屏与restframework-jwt执
    目录1.后台管理simplui的介绍和使用1.后台管理simplui的介绍和使用1.djangoadmin自带了权限控制,但是是前后端混合的,我们可以二次开发,如开发出公司内部的自动化运行,自......
  • MongooseError: Operation `logs.insertOne()` buffering timed out after 10000ms
    我有个model总报错:2022-10-1700:22:15:logadd:MongooseError:Operation`logs.insertOne()`bufferingtimedoutafter10000ms0|tinyurl|atTimeout.<ano......
  • Google Analytics – GA4 & Tag Manager 概念篇
    前言当我们设计好网站或者App后,我们要怎样知道这个产品用户是否满意呢?如果发掘潜在的提升空间呢?等用户反馈?投诉? 显然不是上策,更好的方式是观察.身为一个......
  • SQL Server 错误: 超过了锁请求超时时段 错误1222
    1、症状:打开表或者存储过程,出现异常,查询过久等2、解决方案:2.1最简单的方法:直接重启SQLSERVER服务2.2关闭出现死锁的进程12345--查询死锁进程SELECT ......
  • 8.MongoDB系列之创建副本集(一)
    1.复制简介在MongoDB中,创建副本集后就可以使用复制功能了,副本集是一组服务器,其中一个是用于处理写操作的主节点,还有多个用于保存主节点的数据副本的从节点,如果主节点崩溃......
  • 9.MongoDB系列之创建副本集(二)
    1.如何设计副本集大多数:选取主节点时需要由大多数决定,主节点只有在得到大多数支持时才能继续作为主节点,写操作被复制到大多数成员时就是安全的写操作。这里的大多数定义......
  • 10.MongoDB系列之副本集组成
    1.同步复制是指多台服务器保持相同的数据副本。MongoDB通过保存操作日志(oplog)实现复制功能。oplog存在于主节点local数据库中的一个固定集合,包含了主节点执行的每一次......
  • Docker安装MongoDB并使用Navicat连接
    MongoDB简介:MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。是一个介于关系数据库和非关系数据库之间......
  • MongoDb基本命令
    基本命令查看当前有哪些数据库#方法1showdatabases#方法2showdbs创建数据库/选择数据库usetest2#如果当前没有test2数据库就会创建test2并切换,有的话直接......