http://wosyingjun.iteye.com/blog/2303296
Netty学习:搭建一个简单的Netty服务
Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络应用程序,比如客户端和服务端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的 Socket的开发。Netty 已逐渐成为 Java NIO 编程的首选框架。
项目官方地址:http://netty.io/index.html
一. Netty 的优点:
- API 使用简单,开发门槛低;
- 功能强大,预置了多种编解码功能,支持多种主流协议;
- 定制能力强,可以通过 ChannelHandler 对通信框架进行灵活的扩展;
- 性能高,通过与其它业界主流的 NIO 框架对比,Netty 的综合性能最优;
- 社区活跃,版本迭代周期短,发现的 BUG 可以被及时修复,同时,更多的新功能会被加入;
- 经历了大规模的商业应用考验,质量得到验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它完全满足不同行业的商用标准。
二. 搭建Netty服务:
- 添加pom依赖
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>4.1.0.Final</version>
- </dependency>
- SimpleServer(服务端)
- package com.yingjun.netty.server;
- 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;
- /**
- *
- * Netty中,通讯的双方建立连接后,会把数据按照ByteBuf的方式进行传输,
- * 例如http协议中,就是通过HttpRequestDecoder对ByteBuf数据流进行处理,转换成http的对象。
- *
- */
- public class SimpleServer {
- private int port;
- public SimpleServer(int port) {
- this.port = port;
- }
- public void run() throws Exception {
- //EventLoopGroup是用来处理IO操作的多线程事件循环器
- //bossGroup 用来接收进来的连接
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- //workerGroup 用来处理已经被接收的连接
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- //启动 NIO 服务的辅助启动类
- ServerBootstrap b = new ServerBootstrap();
- b.group(bossGroup, workerGroup)
- //配置 Channel
- .channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) throws Exception {
- // 注册handler
- ch.pipeline().addLast(new SimpleServerHandler());
- }
- })
- .option(ChannelOption.SO_BACKLOG, 128)
- .childOption(ChannelOption.SO_KEEPALIVE, true);
- // 绑定端口,开始接收进来的连接
- ChannelFuture f = b.bind(port).sync();
- // 等待服务器 socket 关闭 。
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- }
- }
- public static void main(String[] args) throws Exception {
- new SimpleServer(9999).run();
- }
- }
- SimpleServerHandler(服务端请求处理Handler)
- package com.yingjun.netty.server;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- public class SimpleServerHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("SimpleServerHandler.channelRead");
- ByteBuf result = (ByteBuf) msg;
- byte[] result1 = new byte[result.readableBytes()];
- // msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中
- result.readBytes(result1);
- String resultStr = new String(result1);
- // 接收并打印客户端的信息
- System.out.println("Client said:" + resultStr);
- // 释放资源,这行很关键
- result.release();
- // 向客户端发送消息
- String response = "hello client!";
- // 在当前场景下,发送的数据必须转换成ByteBuf数组
- ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
- encoded.writeBytes(response.getBytes());
- ctx.write(encoded);
- ctx.flush();
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- // 当出现异常就关闭连接
- cause.printStackTrace();
- ctx.close();
- }
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- ctx.flush();
- }
- }
- SimpleServer(客户端)
- package com.yingjun.netty.server;
- import io.netty.bootstrap.Bootstrap;
- 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;
- import io.netty.channel.socket.nio.NioSocketChannel;
- public class SimpleClient {
- public void connect(String host, int port) throws Exception {
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- Bootstrap b = new Bootstrap();
- b.group(workerGroup);
- b.channel(NioSocketChannel.class);
- b.option(ChannelOption.SO_KEEPALIVE, true);
- b.handler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) throws Exception {
- ch.pipeline().addLast(new SimpleClientHandler());
- }
- });
- // Start the client.
- ChannelFuture f = b.connect(host, port).sync();
- // Wait until the connection is closed.
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- }
- }
- public static void main(String[] args) throws Exception {
- SimpleClient client=new SimpleClient();
- client.connect("127.0.0.1", 9999);
- }
- }
- SimpleServerHandler(客户端请求处理Handler)
- package com.yingjun.netty.server;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- public class SimpleClientHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("SimpleClientHandler.channelRead");
- ByteBuf result = (ByteBuf) msg;
- byte[] result1 = new byte[result.readableBytes()];
- result.readBytes(result1);
- System.out.println("Server said:" + new String(result1));
- result.release();
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- // 当出现异常就关闭连接
- cause.printStackTrace();
- ctx.close();
- }
- // 连接成功后,向server发送消息
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- String msg = "hello Server!";
- ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
- encoded.writeBytes(msg.getBytes());
- ctx.write(encoded);
- ctx.flush();
- }
- }
- 运行结果:
- SimpleClientHandler.channelRead
- Server said:hello client!
- ------------------------------------------
- SimpleServerHandler.channelRead
- Client said:hello Server!
- SimpleServerHandler.channelRead
- Client said:hello Server!