零、socket:
http://haohaoxuexi.iteye.com/blog/1979837
一、NIO(1.0)非阻塞
- NIO的特点:
- Buffer,缓冲区
- Channel,管道
- Selector,多路复用选择器
- NIO的步骤:
二、AIO(NIO2.0)异步非阻塞
使用了异步的channel,调用jdk底层的回掉函数,异步处理。
三、什么是netty(基于NIO2.0)
Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.
四、为什么使用netty
远古:使用的是io,近代是nio,现在是netty(已经封装好了的,相对与nio,API更加的简单)
- netty的特点:
- 责任链,和tomcat中的fitter类似(最后结果交给servlet)避免请求的发送者和接受者直接的耦合关系。
- 异步
Netty的异步事件驱动模型主要涉及到下面几个核心的概念:
- Channel:表示一个与socket关联的通道
- ChannelPipeline: 管道,一个Channel拥有一个ChannelPipeline,ChannelPipeline维护着一个处理链(严格的说是两 个:upstream、downstream),处理链是由很多处理句柄ChannelHandler所构成,每个ChannelHandler处理完以 后会传递给链中的下一个处理句柄继续处理。
- ChannelHandler:处理句柄,用户可以定义自己的处理句柄来处理每个请求,或发出请求前进行预处理,典型的有编码/解码器:decoder、encoder。
- ChannelEvent:事件,是整个模型的处理对象,当产生或触发(fire)一个事件时,该事件会沿着ChannelPipeline处理链依次被处理。
- ChannelFuture: 异步结果,这个是异步事件处理的关键,当一个事件被处理时,可以直接以ChannelFuture的形式直接返回,不用在当前操作中被阻塞。可以通过 ChannelFuture得到最终的执行结果,具体的做法是在ChannelFuture添加监听器listener,当操作最终被执行完 后,listener会被触发,我们可以在listener的回调函数中预定义我们的业务代码。
五、如何使用netty,netty的demo
- 建立连接池
- 继承netty父类实现方法
TimeServer
1 package com.wanghongye.Netty; 2 3 import io.netty.bootstrap.ServerBootstrap; 4 import io.netty.channel.ChannelFuture; 5 import io.netty.channel.ChannelInitializer; 6 import io.netty.channel.ChannelOption; 7 import io.netty.channel.EventLoopGroup; 8 9 import io.netty.channel.nio.NioEventLoopGroup; 10 import io.netty.channel.socket.SocketChannel; 11 import io.netty.channel.socket.nio.NioServerSocketChannel; 12 13 /** 14 * @Description :netty服务端 15 * @author :王红叶 16 * @date(创建日期):2015年9月22日 下午5:15:22 17 * @company(公司):深圳市彩讯科技有限公司 18 * 19 * @History(修改历史): 20 */ 21 public class TimeServer 22 { 23 24 public void bind(int port) throws Exception 25 { 26 EventLoopGroup bossGroup = new NioEventLoopGroup(); 27 EventLoopGroup workGroup = new NioEventLoopGroup(); 28 29 try 30 { 31 ServerBootstrap b = new ServerBootstrap(); 32 b.group(bossGroup, workGroup).channel(NioServerSocketChannel.class) 33 .option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChildChannelHandler()); 34 35 ChannelFuture f = b.bind(port).sync(); 36 37 f.channel().closeFuture().sync(); 38 } 39 finally 40 { 41 bossGroup.shutdownGracefully(); 42 workGroup.shutdownGracefully(); 43 } 44 } 45 46 private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{ 47 48 @Override 49 protected void initChannel(SocketChannel arg0) throws Exception 50 { 51 arg0.pipeline().addLast(new TimeChannelHandler()); 52 } 53 } 54 55 public static void main(String[] args) throws Exception 56 { 57 int port = 8080; 58 if(args != null && args.length>0){ 59 port = Integer.valueOf(args[0]); 60 } 61 new TimeServer().bind(port); 62 } 63 }
TimeChannelHandler
1 package com.wanghongye.Netty; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelHandlerAdapter; 6 import io.netty.channel.ChannelHandlerContext; 7 8 /** 9 * Netty处理类 10 * @Description : 11 * @author :王红叶 12 * @date(创建日期):2015年9月22日 下午4:54:06 13 * @company(公司):深圳市彩讯科技有限公司 14 * 15 * @History(修改历史): 16 */ 17 public class TimeChannelHandler extends ChannelHandlerAdapter 18 { 19 public void channelRead(ChannelHandlerContext ctx, Object msg) 20 throws Exception 21 { 22 ByteBuf byteBuf = (ByteBuf) msg; 23 byte[] req = new byte[byteBuf.readableBytes()]; 24 byteBuf.readBytes(req); 25 26 String body = new String(req, "UTF-8"); 27 System.out.println("*********" + body); 28 String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date( 29 System.currentTimeMillis()).toString() : "BAD ORDER"; 30 ByteBuf byteBufReps = Unpooled.copiedBuffer(currentTime.getBytes()); 31 ctx.write(byteBufReps); 32 33 } 34 35 public void channelReadComplete(ChannelHandlerContext ctx) 36 { 37 ctx.close(); 38 } 39 40 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 41 throws Exception 42 { 43 ctx.close(); 44 } 45 46 }
TimeClient
1 package com.wanghongye.Netty; 2 3 import io.netty.bootstrap.Bootstrap; 4 import io.netty.channel.ChannelFuture; 5 import io.netty.channel.ChannelInitializer; 6 import io.netty.channel.ChannelOption; 7 import io.netty.channel.EventLoopGroup; 8 import io.netty.channel.nio.NioEventLoopGroup; 9 import io.netty.channel.socket.SocketChannel; 10 import io.netty.channel.socket.nio.NioSocketChannel; 11 12 13 14 /** 15 * @Description :netty的客户端 16 * @author :王红叶 17 * @date(创建日期):2015年9月22日 下午5:09:54 18 * @company(公司):深圳市彩讯科技有限公司 19 * 20 * @History(修改历史): 21 */ 22 public class TimeClient 23 { 24 public void connet(int port, String host) throws Exception 25 { 26 EventLoopGroup group = new NioEventLoopGroup(); 27 try 28 { 29 Bootstrap bootstrap = new Bootstrap(); 30 bootstrap.group(group).channel(NioSocketChannel.class) 31 .option(ChannelOption.TCP_NODELAY, true) 32 .handler(new ChildChannelHandler()); 33 34 ChannelFuture f = bootstrap.connect(host, port).sync(); 35 f.channel().closeFuture().sync(); 36 } 37 finally 38 { 39 group.shutdownGracefully(); 40 } 41 } 42 43 private class ChildChannelHandler extends ChannelInitializer<SocketChannel> 44 { 45 46 @Override 47 protected void initChannel(SocketChannel arg0) throws Exception 48 { 49 arg0.pipeline().addLast(new TimeChannelClientHandler()); 50 } 51 } 52 53 public static void main(String[] args) throws Exception 54 { 55 int port = 8080; 56 if (args != null && args.length > 0) 57 { 58 port = Integer.valueOf(args[0]); 59 } 60 new TimeClient().connet(port, "127.0.0.1"); 61 } 62 }
TimeChannelClientHandler
1 package com.wanghongye.Netty; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelHandlerAdapter; 6 import io.netty.channel.ChannelHandlerContext; 7 8 public class TimeChannelClientHandler extends ChannelHandlerAdapter 9 { 10 private final ByteBuf buf; 11 12 public TimeChannelClientHandler() 13 { 14 byte[] req = "QUERY TIME ORDER".getBytes(); 15 buf = Unpooled.buffer(req.length); 16 buf.writeBytes(req); 17 } 18 19 public void channelActive(ChannelHandlerContext ctx) 20 { 21 ctx.writeAndFlush(buf); 22 } 23 24 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 25 { 26 ByteBuf byteBuf = (ByteBuf) msg; 27 byte[] req = new byte[byteBuf.readableBytes()]; 28 byteBuf.readBytes(req); 29 30 String body = new String(req, "UTF-8"); 31 System.out.println("###########" + body); 32 } 33 34 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 35 throws Exception 36 { 37 ctx.close(); 38 } 39 }
(NO RUN SUCCESS)
六、项目中如何使用netty
在pns(TCP是同步的)和统一配置中使用netty,主要使用了netty的异步和socket。
七、关于netty的资料
- 《netty权威指南》
- http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html
- http://www.cnblogs.com/NanguoCoffee/archive/2010/12/10/1902491.html
八、netty的相关讨论
- 为什么说netty是异步的?允许客户端最大的同时连接数:服务器有开放那么多文件句柄数 支持那么多长连接 只要服务器资源够就行,另外tomcat自己也会限制连接数。netty的异步体现在:1、服务端不持有连接,使用的是轮询的方法2、channel通道是异步的3、使用了channel future回调
- netty如何编码解码,TCP自带了拆包粘包的功能,netty把他们封装好了,然后处理内容我们需要自己实现