go中如何处理粘性tcp包?

时间:2018-06-10 09:26:53

标签: sockets go networking tcp network-programming

我有一个tcp服务器和一个客户端,服务器执行以下操作

func providerCallback(conn net.Conn) {
    reader := bufio.NewReader(conn)
    var err error
    for {
        lenbyte, _ := reader.Peek(4)
        reader.Discard(4)
        slen := int(binary.BigEndian.Uint32(lenbyte))
        data, err = reader.Peek(slen)
        process(data)
        reader.Discard(slen)
    }
}

客户端似乎比进程可以处理的更快地发送数据包,因此我想在bufio中缓冲请求并稍后处理。

然而,由于bufio的大小是固定的(4096,即使我可以增加它,它仍然是固定的),这意味着我不能手动Reset它因为可能有一个包切割在bufio的最后,如下

  

|普通数据...... [包P的前20个字节] | [包P的其余部分]

     

| ------------------- bufio的大小------------------ |

如何拼接被切断的数据包,并将bufio重新用于以后的数据包?

1 个答案:

答案 0 :(得分:0)

例如,

import (
    "bufio"
    "encoding/binary"
    "io"
    "net"
)

func providerCallback(conn net.Conn) error {
    rdr := bufio.NewReader(conn)
    data := make([]byte, 0, 4*1024)
    for {
        n, err := io.ReadFull(rdr, data[:4])
        data = data[:n]
        if err != nil {
            if err == io.EOF {
                break
            }
            return err
        }
        dataLen := binary.BigEndian.Uint32(data)
        if uint64(dataLen) > uint64(cap(data)) {
            data = make([]byte, 0, dataLen)
        }
        n, err = io.ReadFull(rdr, data[:dataLen])
        data = data[:n]
        if err != nil {
            return err
        }

        process(data)
    }
    return nil
}

func process([]byte) {}