Этот ответ предполагает, что цель программы - передать данные клиенту. Этот ответ включает в себя информацию в комментариях от torek и limon.
Документация для Read говорит
Read читает до байтов len (p) в p. Он возвращает количество прочитанных байтов (0 <= n <= len (p)) и обнаруженную ошибку. Даже если Read возвращает n <len (p), он может использовать все p как пустое место во время вызова. Если некоторые данные доступны, но не len (p) байтов, Read обычно возвращает то, что доступно, вместо ожидания большего. </p>
Вторая программа может не прочитать все данные, потому что Read может вернуть доступные данные вместо того, чтобы ждать большего. Вторая программа может не записать все данные, потому что чтение может вернуть данные и ошибку.
Давайте сосредоточимся на первой программе, потому что она более корректна. Программа может выполнять несколько вызовов Read и Write для одного соединения, но это не означает повторное использование соединения.
Лучше defer c.Close()
в начале функции, чем разбрасывать вызовы до c.Close()
по всей функции. Отсрочка обеспечивает закрытие соединения независимо от выхода из функции.
func handleConnection(c net.Conn) {
defer c.Close()
buf := make([]byte, 4096)
for {
n, err := c.Read(buf)
if err != nil || n == 0 {
break
}
n, err = c.Write(buf[0:n])
if err != nil {
break
}
}
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}
Read может вернуть некоторые данные, а также ошибку. Обработайте любые данные, возвращенные до обработки ошибки:
func handleConnection(c net.Conn) {
defer c.Close()
buf := make([]byte, 4096)
for {
n, er := c.Read(buf)
if n > 0 {
_, ew := c.Write(buf[:n])
if ew != nil {
break
}
}
if er != nil {
break
}
}
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}
Используйте io.Copy вместо записи копии logi c в приложении. Функция io.Copy дает все детали правильно. Кроме того, io.Copy может использовать некоторые низкоуровневые оптимизации для копирования данных из одного соединения в другое.
func handleConnection(c net.Conn) {
defer c.Close()
io.Copy(c, c)
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}