Netty介绍
大约 3 分钟
一、Netty 简介
Netty是由Jboss提供的一个Java开源框架,现为 Github上的独立项目。Netty提供异步的、时间驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。
二、Hello Netty
接下来我们就开始从一个简单地demo,进入netty的世界吧。
该demo实现了创建一个Netty服务器和一个netty客户端,服务端接收到客户端请求的时候便打印相应的信息。
1、NettyServer
public class NettyServer {
private final int port;
public NettyServer(int port) {
this.port = port;
}
public static void main(String[] args) throws InterruptedException {
int port = 9999;
NettyServer echoServer = new NettyServer(port);
System.out.println("服务器启动");
echoServer.start();
System.out.println("服务器关闭");
}
public void start() throws InterruptedException {
final NettyServerHandler serverHandler = new NettyServerHandler();
/*线程组*/
EventLoopGroup group = new NioEventLoopGroup();
try {
/*服务端启动必须*/
ServerBootstrap b = new ServerBootstrap();
b.group(group)/*将线程组传入*/
.channel(NioServerSocketChannel.class)/*指定使用NIO进行网络传输*/
.localAddress(new InetSocketAddress(port))/*指定服务器监听端口*/
/*服务端每接收到一个连接请求,就会新启一个socket通信,也就是channel,
所以下面这段代码的作用就是为这个子channel增加handle*/
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
/*添加到该子channel的pipeline的尾部*/
ch.pipeline().addLast(serverHandler);
}
});
ChannelFuture f = b.bind().sync();/*异步绑定到服务器,sync()会阻塞直到完成*/
f.channel().closeFuture().sync();/*阻塞直到服务器的channel关闭*/
} finally {
group.shutdownGracefully().sync();/*优雅关闭线程组*/
}
}
}
2、NettyServerHandler
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
/*客户端读到数据以后,就会执行*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf)msg;
System.out.println("Server accept"+in.toString(CharsetUtil.UTF_8));
ctx.write(in);
}
/*** 服务端读取完成网络数据后的处理*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
/*** 发生异常后的处理*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
}
}
3、NettyClient
public class NettyClient {
private final int port;
private final String host;
public NettyClient(int port, String host) {
this.port = port;
this.host = host;
}
public void start() throws InterruptedException {
/*线程组*/
EventLoopGroup group = new NioEventLoopGroup();
try{
/*客户端启动必备*/
Bootstrap b = new Bootstrap();
b.group(group)/*把线程组传入*/
/*指定使用NIO进行网络传输*/
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host,port))
.handler(new NettyClientHandler());
/*连接到远程节点,阻塞直到连接完成*/
ChannelFuture f = b.connect().sync();
/*阻塞程序,直到Channel发生了关闭*/
f.channel().closeFuture().sync();
}finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws InterruptedException {
new NettyClient(9999,"127.0.0.1").start();
}
}
4、NettyClientHandler
public class NettyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
/*客户端读到数据以后,就会执行*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg)
throws Exception {
System.out.println("client acccept:"+msg.toString(CharsetUtil.UTF_8));
}
/*连接建立以后*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer(
"Hello Netty",CharsetUtil.UTF_8));
//ctx.fireChannelActive();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt);
}
}
三、总结
使用Netty大大简化了我们的开发工作量,并将原生JDK复杂的Selector、ByteBuffer、ServerSocketChannel、SocketChannel等组件进行封装。使我们开发者不需要关系具体底层的运行原理和机制。进行模板化的开发。提高开发的效率、以及容错率。