Я пишу простой сервис в стиле TLV, использующий TCP in go, который должен обрабатывать несколько соединений и разрешать отправку нескольких сообщений по одному и тому же соединению.
Мне нужно иметь возможностьчтобы гарантировать, что сообщение с неправильной длиной не блокирует соединение на неопределенный срок, но я должен убедиться, что последующие сообщения могут быть отправлены по тому же соединению без истечения времени ожидания.
Я использую io.ReadFull
для чтения вфиксированное количество байтов, которые содержат тип и длину, а затем, когда я получаю length
, я снова звоню io.ReadFull
и читаю length
количество байтов.
Если я читаю в4 байта для типа и длины, но клиент отправляет только 3 по любой причине, io.ReadFull
зависнет. Точно так же, если клиент отправляет 300
для длины, но длина должна быть только 200
, io.ReadFull
будет зависать, блокируя все коммуникации на этом канале.
Я пытался использовать conn.SetReadDeadline()
и установив его на 5 секунд для этого примера. Это приводит к тайм-ауту соединения, если отправлена неправильная длина, и это здорово. Проблема заключается в том, что время ожидания соединения истечет, если следующий запрос не будет отправлен до истечения> 5 секунд.
// ...
for {
conn, err := lis.Accept()
if err != nil {
fmt.Println(err)
continue
}
fmt.Println("Connected")
go handleC(conn)
}
func handleC(conn net.Conn) {
for {
err := conn.SetReadDeadline(time.Now().Add(5 * time.Second))
if err != nil {
fmt.Println(err)
break
}
l, err := readTL(conn)
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
fmt.Println("Timeout", err)
break
}
fmt.Println("Other error"), err
break
}
v, err := readV(conn, l)
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
fmt.Println("Timeout", err)
break
}
fmt.Println("Other error"), err
break
}
// go doStuffWithv()
}
}
func readTL(conn net.Conn) (l int, err error) {
buf := make([]byte, 4)
n, err := io.ReadFull(conn, buf)
if err != nil {
return l, err
}
fmt.Printf("Read %d bytes\n", n)
// getLengthFromTL()
return l, err
}
func readV(conn net.Conn, l int) (v []byte, err error) {
buf := make([]byte, l)
n, err := io.ReadFull(conn, buf)
if err != nil {
return v, err
}
fmt.Printf("Read %d bytes\n", n)
return v, err
}
Если клиент отправляет один запрос с соответствующим TL, все работает как задумано. Тем не менее, если один и тот же клиент не отправляет второе сообщение в течение 10 секунд, до истечения этого времени соединение прекратит работу с ошибкой tls: use of closed connection
Есть ли способ гарантировать, что этого не произойдет?
OneЯ пытался сделать это в случае тайм-аута, он просто продолжается, а не прерывается. Я добавил еще одну проверку на наличие ошибок, чтобы узнать, является ли она EOF
, и прервите, если это так.
Мое первое впечатление - это работает, но я не уверен, что существуют случаи, когда тайм-аут соединения можетозначает, что соединение разорвано и не должно больше использоваться или нет, или если это всегда будет возвращать ошибку EOF
.