golang网络库中tcp的几种报错
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)
}