Это 12-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления
Введение
В предыдущей серии статей мы использовали netty в качестве сервера чата и SocketChannel, используемый сервером чата, что означает, что базовый протокол использует Scoket. Сегодня мы покажем вам, как использовать протокол UDP в netty.
UDP-протокол
UDP (протокол пользовательских дейтаграмм), также известный как протокол пользовательских дейтаграмм.
Основная функция и изюминка UDP заключается не в том, какие функции он вводит, а в тех функциях, которые он игнорирует: отсутствие гарантии доставки сообщения, отсутствие гарантии порядка доставки, отсутствие отслеживания состояния соединения, отсутствие необходимости контроля перегрузки.
Давайте посмотрим на пакеты UDP:
UDP — это протокол без установления соединения.Отправителю нужно только отправлять пакеты данных.Он не отвечает за обработку и обеспечение того, чтобы данные были успешно отправлены, обработаны ли данные и т.д. Его единственная функция — посылать.
Существует специальный класс, который представляет UDP в JDK, который называется: java.net.DatagramPacket, а также есть java.nio.channels.DatagramChannel в NIO, который специально отвечает за обработку каналов UDP.
Здесь нам нужен netty.У Netty также есть два вышеуказанных класса для протокола UDP.Хотя имена одинаковы, соответствующие пакеты разные. Они есть:
io.netty.channel.socket.DatagramPacket и io.netty.channel.socket.DatagramChannel, конечно, эти два класса в netty являются улучшениями собственных классов JDK.
Сначала посмотрите на определение DatagramPacket в netty:
public class DatagramPacket
extends DefaultAddressedEnvelope<ByteBuf, InetSocketAddress> implements ByteBufHolder
Класс DatagramPacket реализует интерфейс ByteBufHolder, указывая, что он хранит ByteBuf. Затем он наследуется от DefaultAddressedEnvelope, этот класс является инкапсуляцией адреса, где ByteBuf представляет собой тип доставки сообщения, InetSocketAddress представляет собой адрес цели, это инкапсуляция IP-адреса + номера порта.
Из приведенного выше протокола UDP мы знаем, что UDP нужно знать только целевой адрес и соответствующее сообщение, поэтому данных, содержащихся в DatagramPacket, достаточно.
DatagramChannel используется для передачи DatagramPacket.Поскольку DatagramChannel является интерфейсом, NioDatagramChannel обычно используется в качестве реального класса.
Преобразование String и ByteBuf
Как мы упоминали ранее, канал в netty принимает только тип данных ByteBuf.Если он будет записан напрямую в String, будет сообщено об ошибке.В предыдущей серии статей мы говорили о двух методах обработки.Первый заключается в использовании ObjectEncoder и ObjectDecoder для записи в ByteBuf До сериализации объектов этот подходит не только для String, но и для объектов Object.
Во-вторых, использовать StringEncoder и StringDecoder для конкретной работы с кодированием и декодированием String.Этот вид обработки может иметь дело только с преобразованием String и недопустим для Object.
Если вы не хотите использовать эти кодировщики и декодеры, вы можете напрямую использовать ByteBuf и String для преобразования.
Например, чтобы записать String в ByteBuf, вы можете вызвать команду Unpooled.copiedBuffer следующим образом:
Unpooled.copiedBuffer("开始广播", CharsetUtil.UTF_8)
Чтобы преобразовать ByteBuf в String, вы можете позвонить:
byteBuf.toString(CharsetUtil.UTF_8)
Построить пакет дейтаграммы
DatagramPacket может принимать в общей сложности три параметра: данные для отправки, адрес для получения пакета данных и адрес для отправки пакета данных.
Здесь нас не волнует адрес отправки пакета данных, поэтому нужны только два параметра.Для клиента мы отправляем серверу сообщение «начать вещание», сообщая серверу, что он может отправить ответное сообщение на клиент, следующим образом:
new DatagramPacket(
Unpooled.copiedBuffer("开始广播", CharsetUtil.UTF_8),
SocketUtils.socketAddress("255.255.255.255", PORT))
Выше мы использовали SocketUtils.socketAddress для создания специального адреса, 255.255.255.255 — это специальный широковещательный адрес, что означает все хосты, потому что наш клиент не знает адрес сервера, поэтому для трансляции используйте 255.255.255.255.
Сконструированный DatagramPacket имеет в себе метод sender(), который можно использовать для получения адреса клиента, поэтому отправляемый пакет может быть построен следующим образом на стороне сервера:
new DatagramPacket(
Unpooled.copiedBuffer("广播: " + nextQuote(), CharsetUtil.UTF_8), packet.sender())
Запустить клиент и сервер
Запуск клиента и сервера UDP немного отличается от сокета: если это сокет, используется канал NioSocketChannel, а если это UDP, используется NioDatagramChannel. Ниже приведен код запуска на стороне сервера:
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPServerHandler());
b.bind(PORT).sync().channel().closeFuture().await();
} finally {
group.shutdownGracefully();
}
Обратите внимание, что здесь нам нужно установить для ChannelOption.SO_BROADCAST значение true, потому что UDP отправляет сообщения в виде широковещательных передач.
Реализация клиента немного отличается от сокета, ниже приведена стартовая реализация клиента:
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPClientHandler());
Channel ch = b.bind(0).sync().channel();
Для UDP нет привязки к адресу, поэтому вызовите bind(0) в Bootstrap.
Суммировать
В этой статье объясняется реализация протокола UDP в netty. UDP проще, чем соединения Socket.
Примеры этой статьи могут относиться к:learn-netty4
Эта статья была включена вwoohoo. Флойд press.com/11-Netty-UD…
Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!
Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!