网络编程:读取完整数据包的细节处理(适用于Unix domain socket)

@李彪  June 8, 2018

对于TCP网络编程,读取对方数据是一个最普遍的操作,但是如何把对方的数据包完整读取到,这个看似简单的问题,需要小心处理,下面发一份公众代码,无论是书籍还是网上问答基本给出的都是这个答案。

var dataBytes bytes.Buffer
buf := make([]byte, 10);
for {
    n, err := conn.Read(buf)
    if err != nil {
        if err == io.EOF {
            //conn.Close()
        } else {
            log.Fatalln(err)
        }
        break
    }
    dataBytes.Write(buf[:n])
}

这份代码乍一看没什么问题,但是如果仔细想想,什么时候对方才会发送io.EOF ? 只有当TCP链路中确定没有可读数据时,什么时候才可以确定没有数据继续可读?一般代表对方已经关闭,所以用上述条件来结束数据读取的同时也就代表无法通过TCP向对方写入数据了,因为会造成broken pipe异常。

下面分享一份改进代码:

var dataBytes bytes.Buffer
buf := make([]byte, 10);
caplen := cap(buf)  //获取总容量
for {
    n, err := conn.Read(buf)
    if err == nil {
        dataBytes.Write(buf[:n])
        if n < caplen {
            break;
        }
    } else {
        break;
    }
}

这样读取数据,我们就可以保持TCP链路的活性。


评论已关闭