Ответ на UDP-пакет в Go
Слушатель не обязан заранее знать, кто напишет первым. Адрес отправителя приходит вместе с каждым принятым пакетом, и именно на него отправляют ответ, а не на строку из конфигурации, если клиент сидит за другим портом.
Запись ответа привязана к тому же открытому сокету, что и прием: первым аргументом идут байты, вторым структура адреса из результата чтения.
Примем одно сообщение и вернем короткий текст тому же хосту:
package main
import (
"fmt"
"net"
)
func main() {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:9091")
if err != nil {
fmt.Println("resolve error")
return
}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
fmt.Println("listen error")
return
}
defer conn.Close()
buf := make([]byte, 1024)
n, remote, err := conn.ReadFromUDP(buf)
if err != nil {
fmt.Println("read error")
return
}
fmt.Println("got", string(buf[:n]))
_, err = conn.WriteToUDP([]byte("pong"), remote)
if err != nil {
fmt.Println("reply error")
return
}
fmt.Println("replied")
}
На экране сначала "got" с текстом
запроса, затем "replied". Без
работающего отправителя на другом конце
программа так и будет ждать на чтении.
Несколько клиентов могут слать на один
порт: у каждого пакета свой remote,
и ответ уходит строго тому, чей пакет
обрабатывают сейчас:
package main
import (
"fmt"
"net"
)
func reply(conn *net.UDPConn) {
buf := make([]byte, 256)
n, remote, err := conn.ReadFromUDP(buf)
if err != nil {
return
}
answer := fmt.Sprintf("echo %s", string(buf[:n]))
conn.WriteToUDP([]byte(answer), remote)
}
func main() {
addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:9091")
conn, err := net.ListenUDP("udp", addr)
if err != nil {
fmt.Println("listen error")
return
}
defer conn.Close()
reply(conn)
fmt.Println("done")
}
Дано сообщение ответа:
answer := []byte("ack")
После одного приема на "127.0.0.1:9091"
отправьте answer на адрес из
результата чтения.
Дан фрагмент:
n, remote, _ := conn.ReadFromUDP(buf)
conn.WriteToUDP([]byte("pong"), remote)
Скажите, почему для ответа берут remote,
а не строку "127.0.0.1:9091".
Скажите, что случится с ответом, если отправитель уже закрыл свой сокет, но слушатель все равно шлет пакет на старый адрес из памяти.