Zihan
Zihan

Reputation: 427

How to deal with sticky tcp packet in go?

I have a tcp server and a client, the server does the following

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)
    }
}

The client seems to send packet faster than process can deal with, therefore I'd like to buffer the requests in bufio and process later.

However, as the size of bufio is fixed(4096, even though I can increase it, it is still fixed), which means I can't manually Reset it because there might be a packet cutting of in the end of bufio, as follows

|normal data... [First 20 bytes of packet P] | [the rest of packet P]

|------------------- size of bufio ------------------|

How can I splice packet that is cut off, and reuse the bufio for later packets?

Upvotes: 0

Views: 1777

Answers (1)

peterSO
peterSO

Reputation: 166598

For example,

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) {}

Upvotes: 1

Related Questions