Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。
在Netty官网上是如上定义Netty的。Netty利用了Java的高级网络能力,提供了一个比JDK原生API更容易使用且功能更强大的客户端/服务器框架。
Netty与Tomcat的区别
提到服务器,大家可能更多的想到的会是Tomcat。Netty与Tomcat最大的区别就在于通信协议,Tomcat是基于HTTP协议的,它的实质是一个基于HTTP协议的web容器,但是Netty不一样,他能通过codec来自己编码/解码字节流,即Netty可以自定义各种通信协议,这就是Netty与Tomcat最大的不同。
Netty的简单应用
依然是用时间服务器来呈现Netty的应用,Netty版本使用的是4.1.46.Final。
首先是服务器端,NettyServerTest类,用于构建Netty相关的组件,并进行初始化:
package com.test.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class NettyServerTest {
public void bind(int port) throws InterruptedException {
// NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器
// 第一个经常被叫做‘boss’,用来接收进来的连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
// 第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// ServerBootstrap 是一个启动 NIO 服务的辅助启动类
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// 设置 socket 的参数选项
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new childChannelHandler());
// 绑定端口,同步等待成功
ChannelFuture f = b.bind(port).sync();
// 等待服务端监听端口关闭
f.channel().closeFuture().sync();
}finally {
// 优雅退出,释放线程资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
/**
* ChannelInitializer 是一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel
* @author
*
*/
private class childChannelHandler extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel arg0) throws Exception {
arg0.pipeline().addLast(new ServerTestHandler());
}
}
public static void main(String[] args) throws InterruptedException {
int port = 8888;
new NettyServerTest().bind(port);
}
}
然后我们还需要构建一个用于处理服务器端接收到的客户端连接的Handle类,读取客户端消息和向客户端发送response:
package com.test.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class ServerTestHandler extends ChannelInboundHandlerAdapter {
/**
* 每当从客户端收到新的数据时,channelRead()方法会在收到消息时被调用
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body =