Netty通过UDP广播
Netty 是一个利用 Java 的高级网络的能力,隐藏了Java背后的复杂性然后提供了一个易于使用的 API 的客户端/服务器框架。支撑nio编程,可以提升并发性能;netty的特性是零拷贝,直接在内存中开辟一块,省去了socket缓冲区;封装完美使得编码简便
Netty的bootstrap
引导类的层次结构包括一个抽象的父类和两个具体的引导子类:

| 方法 | 描述 |
|---|---|
| group | 设置用于处理所有事件的 EventLoopGroup |
| channel | 指定服务端或客户端的 Channel |
| channelFactory | 如果引导没有指定Channel,那么可以指定ChannelFactory来创建Channel |
| localAddress | 指定Channel需要绑定的本地地址,如果不指定,则将由系统随机分配一个地址 |
| remoteAddress | 设置Channel需要连接的远程地址 |
| attr | 指定新创建的Channel的属性值 |
| handler | 设置添加到ChannelPipeline中的ChannelHandler |
| connect | 连接到远程主机,返回ChannelFuture,用于连接完成的回调 |
| bind | 绑定指定地址,返回ChannelFuture,用于绑定完成的回调 |
引导客户端和无连接协议Booststrap
当需要引导客户端或一些无连接协议时,需要使用 Bootstrap 类。Bootstrap 类负责创建管道给客户或应用程序,作为客户端,我们需要使用到 connect API 来连接到远程 服务端,其过程如下:

引导服务端ServerBootstrap
ServerBootstrap 负责Netty应用程序的服务端引导,作为服务端,我们需要使用 bind API来 与本地地址绑定,从而接收客户端连接,其过程如下:

image.png
导入maven依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
<version>3.10.5.Final</version>
</dependency>
Server
@Data
@Slf4j
@Component
@ConfigurationProperties(prefix = "netty")
@ConditionalOnProperty(prefix = "netty.udp.server", name = "enable", havingValue = "true", matchIfMissing = false)
public class NettyUdpServer {
private Bootstrap bootstrap = new Bootstrap();
private NioEventLoopGroup group = new NioEventLoopGroup();
private Channel channel;
private Integer clientPort;
private Integer serverPort;
@PostConstruct
public void start() throws InterruptedException {
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 100)
.option(ChannelOption.SO_SNDBUF, 1024 * 1024 * 100)
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new NettyUdpServerHandler());
}
});
channel = bootstrap.bind(serverPort).sync().channel();
log.info("----------------------------UdpServer start success");
}
@PreDestroy
public void destory() throws InterruptedException {
group.shutdownGracefully().sync();
log.info("----------------------------关闭NettyServer");
}
public void sendToAll(String msg) {
try {
this.channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(
msg, CharsetUtil.UTF_8), new InetSocketAddress("255.255.255.255", clientPort)));
} catch (Exception e) {
return;
}
}
}
Client
@Data
@Component
@Configuration
@Slf4j
@ConfigurationProperties(prefix = "netty")
@ConditionalOnProperty(prefix = "netty.udp.client", name = "enable", havingValue = "true", matchIfMissing = false)
public class NettyUdpClient {
private Bootstrap bootstrap = new Bootstrap();
private NioEventLoopGroup group = new NioEventLoopGroup();
private Channel channel;
private Integer clientPort;
private Integer serverPort;
private String serverIp;
@PostConstruct
public void start() throws InterruptedException {
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 100)
.option(ChannelOption.SO_SNDBUF, 1024 * 1024 * 100)
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new NettyUdpClientHandler());
}
});
channel = bootstrap.bind(clientPort).sync().channel();
log.info("----------------------------UdpClient start success");
}
@PreDestroy
public void destory() throws InterruptedException {
group.shutdownGracefully().sync();
log.info("----------------------------关闭Netty");
}
public void sendToServer(String msg) {
try {
MessageProtocol protocol = new MessageProtocol(msg.getBytes(CharsetUtil.UTF_8).length,msg.getBytes(CharsetUtil.UTF_8));
this.channel.writeAndFlush(new DatagramPacket(protocol.toByteBuf(), new InetSocketAddress(serverIp, serverPort)));
} catch (Exception e) {
return;
}
}
}
Handler
@Slf4j
public class NettyUdpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
System.out.printf("-------udp客户端收到数据:" + datagramPacket.content().toString(CharsetUtil.UTF_8));
}
}