一:简介
- Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性
二:编码
- 引入程序包
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.36.Final</version>
</dependency>
- 搭建netty服务
@Slf4j
@Component
public class NettyServer implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
String tcpIp = ""
String tcpPort = ""
start(new InetSocketAddress(tcpIp, Integer.valueOf(tcpPort)));
}
public void start(InetSocketAddress socketAddress) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup(200);
ServerBootstrap bootstrap = new ServerBootstrap()
.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerChannelInitializer())
.localAddress(socketAddress)
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true);
try {
ChannelFuture future = bootstrap.bind(socketAddress).sync();
log.info("Netty服务器启动开始监听端口: {}", socketAddress.getPort());
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("Netty端口冲突,异常信息:{}", e.getMessage());
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
- netty服务初始化器
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast("handler", new NettyServerHandler());
}
}
- netty服务端处理器
@Slf4j
@Component
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
private static NettyServerHandler nettyServerHandler;
@PostConstruct
public void init(){
nettyServerHandler = this;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("TCP对象线程: {}", ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String message = onMessage(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
close(ctx);
}
public static String onMessage(Object msg) {
ByteBuf buf = (ByteBuf)msg;
byte [] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
String message = HexEcodeUtil.ByteArrayToHexStr(bytes);
return message;
}
public static void writeToClient(final String receiveStr, ChannelHandlerContext ctx,String mark) {
try {
ByteBuf bufff = Unpooled.buffer();
bufff.writeBytes(HexEcodeUtil.hexStrToBinaryStr(receiveStr));
ctx.writeAndFlush(bufff).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
StringBuilder sb = new StringBuilder("");
if(!StringUtils.isEmpty(mark)){
sb.append("【").append(mark).append("】");
}
if (future.isSuccess()) {
log.info("回写成功:" + sb.toString() + "{}",receiveStr);
} else {
log.info("回写失败:" + sb.toString() + "{}",receiveStr);
}
}
});
} catch (Exception e) {
e.printStackTrace();
log.error("调用通用writeToClient()异常:",e);
close(ctx);
}
}
public static void close(ChannelHandlerContext ctx) {
if (ctx != null) {
try {
log.info("关闭netty:{}", ctx);
ctx.close();
} catch (Exception e) {
log.error("关闭netty异常{}", e);
}
}
}
}