Сегодня, когда я пытаюсь отправить данные 100M на мой сервер (очень простой TCP-сервер, также написанный на Golang), я обнаружил, что метод TCPConn.Write возвращает 104857600 и ошибку nil, а затем закрываю сокет. Но мой сервер только получает очень мало данных. Я думаю, это потому, что метод Write работает в асинхронном режиме, поэтому, хотя метод возвращает 104857600, на сервер отправляется только небольшое количество данных. Поэтому я хочу знать, есть ли способ установить работу записи в режиме синхронизации или как определить, все ли данные отправляются на сервер из сокета.
Код выглядит следующим образом:
Сервер:
const ListenAddress = "192.168.0.128:8888"
func main() {
var l net.Listener
var err error
l, err = net.Listen("tcp", ListenAddress)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer l.Close()
fmt.Println("listen on " + ListenAddress)
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
//logs an incoming message
fmt.Printf("Received message %s -> %s \n", conn.RemoteAddr(), conn.LocalAddr())
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
rcvLen := 0
rcvData := make([]byte,20 * 1024 * 1024) // 20M
for {
l , err := conn.Read(rcvData)
if err != nil {
fmt.Printf("%v", err)
return
}
rcvLen += l
fmt.Printf("recv: %d\r\n", rcvLen)
conn.Write(rcvData[:l])
}
}
Клиент:
conn, err := net.Dial("tcp", "192.168.0.128:8888")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer conn.Close()
data := make([]byte, 500 * 1024 * 1024)
len, err := conn.Write(data)
fmt.Println("send len: ", len)
Выход клиента:
send len: 524288000
Выход сервера:
listen on 192.168.0.128:8888
Received message 192.168.0.2:50561 -> 192.168.0.128:8888
recv: 166440
recv: 265720
EOF
Я знаю, что если я смогу заставить клиента некоторое время подождать методом SetLinger, все данные будут отправлены на сервер до закрытия сокета. Но я хочу найти способ заставить сокет отправлять все данные перед возвратом без вызова SetLinger (). Заранее спасибо. Пожалуйста, извините за мой плохой английский.