golang的net包设置超时有三个函数, 定义在net.Conn, 它是一个interface, 如下:
SetDeadline(t time.Time) error // 设置读写超时, 如果超时, 会返回超时错误. 等同于同时设置以下两个函数.
SetReadDeadline(t time.Time) error // 设置读超时, 如果超时, 会返回超时错误.
SetWriteDeadline(t time.Time) error // 设置写超时, 如果超时, 会返回超时错误.
本文主要验证的是写超时, 并判断超时错误, 主要是通过reflect和unsafe把err转成(*net.OpError). 测试代码如下:
package main
import (
"fmt"
"net"
"os"
"reflect"
"syscall"
"time"
"unsafe"
)
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:10299")
if err != nil {
fmt.Printf("listen fail, err: %v\n", err)
os.Exit(-1)
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("accept fail, err: %v\n", err)
continue
}
fmt.Printf("accept: %s successfully!\n", conn.RemoteAddr())
go write(conn)
}
}
func write(c net.Conn) {
defer c.Close()
now := time.Now()
begin := now.Local().UnixNano() / (1000 * 1000)
// 为了验证超时, 在循环外设置, 2秒超时
c.SetWriteDeadline(now.Add(time.Second * 2))
for {
if _, err := c.Write([]byte("Write Msg")); err != nil {
// 这个错误是不能转换*net.OpError
if err == syscall.EINVAL {
return
}
// 转换成*net.OpError
opErr := (*net.OpError)(unsafe.Pointer(reflect.ValueOf(err).Pointer()))
if opErr.Err.Error() == "i/o timeout" {
end := time.Now().Local().UnixNano() / (1000 * 1000)
fmt.Printf("Write timeout! end: %d, begin: %d, timeOut: %dms", end, begin, end-begin)
return
}
return
}
time.Sleep(time.Millisecond)
}
}
测试结果如下:
结束:
这是通过指针转换并通过比较字符串的方式判断的, 如果哪位同学有更方便的方法, 请告知以下, 谢谢.