Golang — нестабильность с Gob по протоколу TCP

# #go #tcp #gob

Вопрос:

У меня возникла проблема с нестабильностью при использовании gob для TCP-связи.

Основная проблема заключается в том, что если я передаю данные «быстро», я либо получаю ошибки, когда сервер прерывает соединение, либо пакет просто не поступает на сервер. Теперь, если я добавлю задержку в 20 мс между пакетами, все будет работать так, как ожидалось.

К сожалению, я не могу связать это с игровой площадкой, так как я запускаю ее в трех разных библиотеках, но я вставил код essential/culprit.

Я предполагаю, что если у меня нет таймера задержки, я перезаписываю поток. Есть какие-нибудь идеи?

Обновление: Заменив приемник на bufio.NewReader(c.сокет), я на самом деле могу получить сообщение об ошибке: «gob: неизвестный идентификатор типа или поврежденные данные», которое похоже на ту же проблему, что и https://github.com/golang/go/issues/1238#event-242248991

 //client -> server, running as a goroutine
func (c *Client) transmitter() {
    d := 20 * time.Millisecond
    timer := time.NewTimer(d) //silly hack
    for {
        select {

        case gd := <- c.broadcast:
            <- timer.C

            Write(c.socket, gd.Data, gd.NetworkDataType)

            timer.Reset(d) //refreshing timer
        }
    }
}

//server <- client, running as a goroutine
func (c *client) receiver (s *Server){
    for {
        in, err := Read(c.socket)
        if err != nil {
            log.println(err)
        }
        //doing stuff
    }
}

func Read(conn net.Conn) (GeneralData, error)  {
    in := GeneralData{}
    if err := gob.NewDecoder(conn).Decode(amp;in); err != nil {
        return in, err
    }
    return in, nil
}

func Write(conn net.Conn, data interface{}, ndt NetworkDataType) {
    err := gob.NewEncoder(conn).Encode(GeneralData{ndt,data})
    if err != nil {
        log.Println("error in write: ", err)
    }
}
 

Комментарии:

1. Вы повторно обертываете одно и то же соединение новыми декодерами, каждый из которых может содержать буферизованные данные.

2. Согласно моим исследованиям, делать это таким образом с новыми декодерами должно быть нормально. Тем не менее, я приближаюсь к рабочей системе, использующей bufio. Чтение и запись.

3. Если это исследование включает в себя чтение документации, вы можете увидеть , что NewDecoder в ней говорится: «Если r это также не будет реализовано io.ByteReader , оно будет завернуто в bufio.Reader » .