Netty通過UDP廣播
Netty 是一個利用 Java 的高級網絡的能力睛约,隱藏了Java背后的復雜性然后提供了一個易于使用的 API 的客戶端/服務器框架。支撐nio編程迹栓,可以提升并發(fā)性能;netty的特性是零拷貝,直接在內存中開辟一塊藕夫,省去了socket緩沖區(qū);封裝完美使得編碼簡便
Netty的bootstrap
引導類的層次結構包括一個抽象的父類和兩個具體的引導子類:
方法 | 描述 |
---|---|
group | 設置用于處理所有事件的 EventLoopGroup |
channel | 指定服務端或客戶端的 Channel |
channelFactory | 如果引導沒有指定Channel,那么可以指定ChannelFactory來創(chuàng)建Channel |
localAddress | 指定Channel需要綁定的本地地址毅贮,如果不指定梭姓,則將由系統(tǒng)隨機分配一個地址 |
remoteAddress | 設置Channel需要連接的遠程地址 |
attr | 指定新創(chuàng)建的Channel的屬性值 |
handler | 設置添加到ChannelPipeline中的ChannelHandler |
connect | 連接到遠程主機,返回ChannelFuture嫩码,用于連接完成的回調 |
bind | 綁定指定地址誉尖,返回ChannelFuture,用于綁定完成的回調 |
引導客戶端和無連接協(xié)議Booststrap
當需要引導客戶端或一些無連接協(xié)議時铸题,需要使用 Bootstrap 類铡恕。Bootstrap 類負責創(chuàng)建管道給客戶或應用程序,作為客戶端丢间,我們需要使用到 connect API 來連接到遠程 服務端探熔,其過程如下:
引導服務端ServerBootstrap
ServerBootstrap 負責Netty應用程序的服務端引導,作為服務端烘挫,我們需要使用 bind API來 與本地地址綁定诀艰,從而接收客戶端連接,其過程如下:
導入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));
}
}