Игрушечный UDP-сервер и клиент на Go. Я сделал это, чтобы познакомиться со стандартным пакетом Go net
, в частности с функциями, связанными с UDP.
Поскольку я узнал, когда писал, вот странное стилистическое несоответствие между тем, как server.go работает с UDP-сокетами, и тем, как client.go делает некоторые «общие» сокеты. Чтобы устранить это несоответствие, я создал client2.go только с функциями UDP, соответствующими server.go.
Я также добавил клиент Python 3, потому что мне больше некуда его поставить.
Сервер прослушивает UDP-пакеты на определенном номере порта. Он блокирует вызов метода net.ReadFromUDP()
.
Если сервер когда-либо получит байты, он распечатает, сколько байтов он получил и откуда, а затем записывает то же количество байтов обратно туда, откуда он их получил.
Клиент создает UDP-соединение с некоторым IP-адресом (v4 или v6) или именем хоста и номером порта на основе информации командной строки. Затем он записывает байты строки, также из командной строки, в UDP-соединение. Он ждет, пока к нему не вернутся несколько байтов или не произойдет ошибка. Тогда оно существует.
Просто, но полно проблем. Никаких таймаутов, никакого заданного количества байтов. Клиент или сервер могут вечно зависать в ожидании пакета, который так и не придет.
$ go build server.go
$ go build client.go
$ go build client2.go
Клиент Python 3 интерпретируется и не требует «сборки».
В окне 1:
$ ./server :: 7890
Accepting a new packet
В окне 2:
$ ./client udp localhost 7890 'some string'
Или:
$ ./client2 fe80::a11:96ff:fe7f:6d74 7890 'some string' [eth0]
Или:
$ ./client1.py localhost 7890 'some string'
Последний аргумент ./client2
не является обязательным. Это имя сетевого интерфейса, через который проходят пакеты. Обратите внимание на содержимое net.UDPAddr
:
type UDPAddr struct {
IP IP
Port int
Zone string // IPv6 scoped addressing zone
}
Элемент Zone используется для маршрутизации локальных адресов канала (префикс fe80:). Имя интерфейса работает как зона. Вызванный с 4-м аргументом, client2
использует этот аргумент как «зону».