go conn.Read() 的阻塞问题

#golang #websocket

golang 主张使用协程代替回调处理web请求,我们可能会写出这样的代码: ``` golang package main import ( "bufio" "fmt" "net" "time" ) func main() { go func() { time.Sleep(time.Second) conn, err := net.Dial("tcp", "127.0.0.1:8080") if err != nil { return } defer conn.Close() n, e := conn.Write([]byte("xxxx;")) fmt.Println("client write ", "xxxx;", n, e) r := bufio.NewReader(conn) msg, e := r.ReadString('\n') fmt.Println("client read ", msg, e) }() go func() { l, e := net.Listen("tcp", ":8080") if e != nil { return } defer l.Close() for { c, e := l.Accept() fmt.Println("accept", e) if e != nil { continue } defer c.Close() r := bufio.NewReader(c) msg, e := r.ReadString('\n') fmt.Println("server rece ", msg) c.Write([]byte("succeed")) fmt.Println("server send ", "succeed") } }() select {} } conn.Read([]byte) ```` 有什么问题呢,事实上这段代码产生了死锁,由于客户端msg不以'\n'结尾,导致r.ReadString('\n')将会阻塞! 换言之, bufio.NewReader 破坏了tcp传输的全双工特性,如果客户端不断开连接,r.ReadString('\n')不会返回 io.EOF ,倘若客户端需要接收消息的话,conn将无法释放! 使用 conn.Read([]byte) 会在msg无数据时阻塞!! 面对数据如何处理: 协议msg格式,规定必须以'\n'结尾,那么可以据此伪造大量异常连接耗尽服务端资源 如果限定长度同样不能保证,超时关闭连接是一种办法,但是tcp本身已经是阻塞读取的情况下,直接读取全部可用值就好啦嘛

上一篇