Как бороться с липким TCP-пакетом в Go? - PullRequest
0 голосов
/ 10 июня 2018

У меня есть 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 следующим образом:

| нормальные данные ... [Первые 20 байтов пакета P] |[остаток пакета P]

| ------------------- размер bufio ------------------ |

Как соединить обрезанный пакет и повторно использовать bufio для последующих пакетов?

1 Ответ

0 голосов
/ 10 июня 2018

Например,

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