最近项目上需要对接UDP协议,之前对接的时候用的是java原生IO流,感觉有些不方便,经过一番查找后发现,还有NIO,以及封装好的netty框架,就感觉可以试一下netty这个框架。
准备知识:netty是什么,为什么要用netty,如何使用netty。
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
Netty是一个基于NIO的网络框架, 封装了Java NIO复杂的底层细节,可以提供简单好用的抽象概念来编程。
Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性
Netty的使用十分方便,只需要在java程序中将依赖导入即可。
maven:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
gradle:
repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
mavenCentral()
}
compile (
'io.netty:netty-all:4.1.10.Final'
)
简易的UDP服务端
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
public class ChineseProverbServer {
public static Channel channel;
public void run(int port) throws Exception{
//启动服务
EventLoopGroup workerGroup = new NioEventLoopGroup();
//优化使用的线程
final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup).channel(NioDatagramChannel.class).handler(new ChannelInitializer<NioDatagramChannel>(){
@Override
protected void initChannel(NioDatagramChannel nioDatagramChannel) throws Exception {
ChannelPipeline pipeline = nioDatagramChannel.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(group,"handler",new ChineseProverbServerHandler());
}
})
.option(ChannelOption.SO_BROADCAST, true)
.option(ChannelOption.SO_RCVBUF, 2048 * 1024)
.option(ChannelOption.SO_SNDBUF, 1024 * 1024);
// 绑定端口,开始接收进来的连接 ,绑定的端口8080
ChannelFuture f = b.bind(port).sync();
//获取channel通道
channel=f.channel();
System.out.println("UDP Server 启动!");
// 等待服务器 socket 关闭 。
// 这不会发生,可以优雅地关闭服务器。
f.channel().closeFuture().await();
}catch (Exception e){
e.printStackTrace();
}finally {
// 优雅退出 释放线程池资源
group.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String [] args) throws Exception{
int port = 8080;
new ChineseProverbServer().run(port);
}
}
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import org.eclipse.leshan.util.Hex;
public class ChineseProverbServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
ByteBuf buf = packet.content();
String ip=packet.sender().getAddress().getHostAddress();
byte[] receiveMsgBytes = new byte[buf.readableBytes()];
buf.readBytes(receiveMsgBytes);
String data= Hex.encodeHexString(receiveMsgBytes);//将16进制byte转换String字符串
System.out.println(data);//具体信息
System.out.println(ip);//IP地址
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.close();
cause.printStackTrace();
}
}