package main import ( "fmt" "net" "time" ) func Serve() { l, err := net.Listen("tcp", ":8888") if err != nil { fmt.Println("err:", err.Error()) } fmt.Println("listen ok") for { conn, err := l.Accept() fmt.Println("accept new conn") if err != nil { fmt.Println("accept err:", err.Error()) return } go ProcessConn(conn) } } func ProcessConn(c net.Conn) { for { c.SetReadDeadline(time.Now().Add(5 * time.Second)) buf := make([]byte, 1025) _, err := c.Read(buf) if err != nil { fmt.Println("read err:", err.Error()) return } fmt.Println("buf:", string(buf)) } } func ProcessConnReDDL(c net.Conn) { //设置的DDL超时以后,如果重新设置ddl,则新的ddl会覆盖老的,进行read的时候以新的ddl来判断是否超时 c.SetReadDeadline(time.Now().Add(1 * time.Second)) time.Sleep(2 * time.Second) for { c.SetReadDeadline(time.Now().Add(5 * time.Second)) buf := make([]byte, 1025) _, err := c.Read(buf) if err != nil { fmt.Println("read err:", err.Error()) return } fmt.Println("buf:", string(buf)) } } func ProcessConnDDL(c net.Conn) { c.SetReadDeadline(time.Now().Add(1 * time.Second)) for { //设置了read ddl以后,在对应时间内没read到数据,或者没进行read操作,则报错read tcp 127.0.0.1:8888->127.0.0.1:56600: i/o timeout c.SetReadDeadline(time.Now().Add(1 * time.Second)) time.Sleep(3 * time.Second) buf := make([]byte, 1025) _, err := c.Read(buf) if err != nil { fmt.Println("read err:", err.Error()) return } fmt.Println("buf:", string(buf)) } } //设置完read ddl以后,只要在ddl内读到了,这个设置就失效了,即使后面sleep更长的时间,后面再读也不会报错 func ProcessConnWithDDl(c net.Conn) { for { c.SetReadDeadline(time.Now().Add(5 * time.Second)) buf := make([]byte, 1025) _, err := c.Read(buf) fmt.Println("buf:", string(buf)) if err != nil { fmt.Println("read err:", err.Error()) return } time.Sleep(10 * time.Second) } } //正常关闭,客户端主动四次挥手 func Client() { dial, err := net.Dial("tcp", ":8888") if err != nil { fmt.Println("dial err:", err.Error()) return } dial.Write([]byte("xxx")) dial.Close() fmt.Println("client close") } //客户端发送RST func RSTClient() { dial, err := net.Dial("tcp", ":8888") if err != nil { fmt.Println("RST dial err:", err.Error()) return } dial.Write([]byte("xxx")) time.Sleep(3 * time.Second) dial.(*net.TCPConn).SetLinger(0) dial.Close() fmt.Println("RST client close") } //客户端自己到DDL了,golang里面客户端ddl以后,不会四次挥手,也不会发RST。如果服务端不设置readddl,就永远不知道客户端断开了。TCP的KeepAlive默认是没开的,即使开,也太长了 func DDlClient() { dial, err := net.Dial("tcp", ":8888") if err != nil { fmt.Println("RST dial err:", err.Error()) return } dial.Write([]byte("xxx")) dial.(*net.TCPConn).SetDeadline(time.Now().Add(1 * time.Second)) time.Sleep(10 * time.Second) //dial.SetDeadline(time.Now().Add(3 * time.Second)) } //客户端发了数据之后,长时间不动,服务端ddl到了以后,服务端报错read tcp 127.0.0.1:8888->127.0.0.1:56783: i/o timeout。这种情况对服务端来说和上种情况一样,只是客户端这里表现不一样 func SleepClient() { dial, err := net.Dial("tcp", ":8888") if err != nil { fmt.Println("RST dial err:", err.Error()) return } dial.Write([]byte("xxx")) time.Sleep(30 * time.Second) } //每秒写一次 func WriteClient() { dial, err := net.Dial("tcp", ":8888") if err != nil { fmt.Println("RST dial err:", err.Error()) return } for { dial.Write([]byte("xxx")) time.Sleep(3 * time.Second) } } //1.client向server发请求,如果server没有监听对应的端口,会报错 connection refused,底层server会给client发RST //2.client写完数据以后正常调用close关闭【四次挥手】,server会读到EOF错误,客户端主动断连,客户端进入timewait //3.client写完数据以后异常关闭【RST】,server报错如下: read tcp 127.0.0.1:8888->127.0.0.1:51136: read: connection reset by peer //4.client写完数据以后,客户端不四次挥手,也不发心跳,server到达read ddl以后,报错: read tcp 127.0.0.1:8888->127.0.0.1:52595: i/o timeout func main() { go Serve() time.Sleep(3 * time.Second) //go Client() //time.Sleep(3 * time.Second) //fmt.Println("==========RST") //go RSTClient() //time.Sleep(3 * time.Second) fmt.Println("==========DDl") go DDlClient() //fmt.Println("===========SLEEP") //go SleepClient() //fmt.Println("======WRITE") //go WriteClient() time.Sleep(30 * time.Second) }