netty初析
来源:互联网 发布:网络性能监控软件 编辑:程序博客网 时间:2024/06/11 21:14
Netty是什么?
本质:JBoss做的一个Jar包
目的:快速开发高性能、高可靠性的网络服务器和客户端程序
优点:提供异步的、事件驱动的网络应用程序框架和工具
通俗的说:一个好使的处理Socket的东东
如果没有Netty?
远古:java.net + java.io
近代:java.nio
其他:Mina,Grizzly
为什么不是Mina?
1、都是Trustin Lee的作品,Netty更晚;
2、Mina将内核和一些特性的联系过于紧密,使得用户在不需要这些特性的时候无法脱离,相比下性能会有所下降,Netty解决了这个设计问题;
3、Netty的文档更清晰,很多Mina的特性在Netty里都有;
4、Netty更新周期更短,新版本的发布比较快;
5、它们的架构差别不大,Mina靠apache生存,而Netty靠jboss,和jboss的结合度非常高,Netty有对google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);
6、Netty比Mina使用起来更简单,Netty里你可以自定义的处理upstream events 或/和 downstream events,可以使用decoder和encoder来解码和编码发送内容;
7、Netty和Mina在处理UDP时有一些不同,Netty将UDP无连接的特性暴露出来;而Mina对UDP进行了高级层次的抽象,可以把UDP当成”面向连接”的协议,而要Netty做到这一点比较困难。
Netty的特性
1. 设计
统一的API,适用于不同的协议(阻塞和非阻塞)
基于灵活、可扩展的事件驱动模型
高度可定制的线程模型
可靠的无连接数据Socket支持(UDP)
2. 性能
更好的吞吐量,低延迟
更省资源
尽量减少不必要的内存拷贝
3. 安全
完整的SSL/TLS和STARTTLS的支持
能在Applet与Android的限制环境运行良好
4. 健壮性
不再因过快、过慢或超负载连接导致OutOfMemoryError
不再有在高速网络环境下NIO读写频率不一致的问题
5. 易用
完善的JavaDoc,用户指南和样例
简洁简单
仅信赖于JDK1.5
Netty包的整体流程
NioServerSocketChannelFactory创建服务端的ServerSocketChannel,采用多线程执行非阻塞IO,和Mina的设计模式一样,都采用了Reactor模式。其中bossExecutor、workerExecutor是两个线程池,bossExecutor用来接收客户端连接,workerExecutor用来执行非阻塞的IO操作,主要是read,write。
下面举例一个简单的Netty服务实现
netty的模式其实就是reactor模式,如下表示reactor模式
服务端
package com.roger.java.pattrn.reactor;import java.net.InetSocketAddress;import java.util.concurrent.Executors;import org.jboss.netty.bootstrap.ServerBootstrap;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelFactory;import org.jboss.netty.channel.ChannelPipeline;import org.jboss.netty.channel.ChannelPipelineFactory;import org.jboss.netty.channel.Channels;import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;import org.jboss.netty.handler.codec.string.StringDecoder;import org.jboss.netty.handler.codec.string.StringEncoder;public class DiscardServer { public static void main(String[] args) throws Exception { ChannelFactory factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap (factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("encode",new StringEncoder()); pipeline.addLast("decode",new StringDecoder()); pipeline.addLast("handler",new DiscardServerHandler()); //pipeline.addLast("handler",new DiscardServerHandler2()); return pipeline; } }); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); Channel bind = bootstrap.bind(new InetSocketAddress(8080)); System.out.println("Server已经启动,监听端口: " + bind.getLocalAddress() + ", 等待客户端注册。。。"); } }
Handler
package com.roger.java.pattrn.reactor;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelHandlerContext;import org.jboss.netty.channel.ChannelStateEvent;import org.jboss.netty.channel.ExceptionEvent;import org.jboss.netty.channel.MessageEvent;import org.jboss.netty.channel.SimpleChannelHandler;public class DiscardServerHandler extends SimpleChannelHandler { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (e.getMessage() instanceof String) { String message = (String) e.getMessage(); System.out.println("Client发来:" + message); e.getChannel().write("Server已收到刚发送的:" + message); System.out.println("\n等待客户端输入。。。"); } super.messageReceived(ctx, e); } @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { System.out.println("有一个客户端注册上来了。。。"); System.out.println("Client:" + e.getChannel().getRemoteAddress()); System.out.println("Server:" + e.getChannel().getLocalAddress()); System.out.println("\n等待客户端输入。。。"); super.channelConnected(ctx, e); } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { e.getCause().printStackTrace(); Channel ch = e.getChannel(); ch.close(); } }
Client
package com.roger.java.pattrn.reactor;import java.net.InetSocketAddress;import java.util.concurrent.Executors;import org.jboss.netty.bootstrap.ClientBootstrap;import org.jboss.netty.channel.ChannelFactory;import org.jboss.netty.channel.ChannelFuture;import org.jboss.netty.channel.ChannelPipeline;import org.jboss.netty.channel.ChannelPipelineFactory;import org.jboss.netty.channel.Channels;import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;import org.jboss.netty.handler.codec.string.StringDecoder;import org.jboss.netty.handler.codec.string.StringEncoder;public class TimeClient { public static void main(String[] args) throws Exception { ChannelFactory factory = new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ClientBootstrap bootstrap = new ClientBootstrap(factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("encode",new StringEncoder()); pipeline.addLast("decode",new StringDecoder()); pipeline.addLast("handler",new TimeClientHandler()); return pipeline; } }); bootstrap.setOption("tcpNoDelay" , true); bootstrap.setOption("keepAlive", true); ChannelFuture future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8080)); // Wait until the connection is closed or the connection attempt fails. future.getChannel().getCloseFuture().awaitUninterruptibly(); // Shut down thread pools to exit. bootstrap.releaseExternalResources(); } }
TimeClientHandler
package com.roger.java.pattrn.reactor;import java.io.BufferedReader;import java.io.InputStreamReader;import org.jboss.netty.channel.ChannelHandlerContext;import org.jboss.netty.channel.ChannelStateEvent;import org.jboss.netty.channel.ExceptionEvent;import org.jboss.netty.channel.MessageEvent;import org.jboss.netty.channel.SimpleChannelHandler;public class TimeClientHandler extends SimpleChannelHandler { private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception{ System.out.println("已经与Server建立连接。。。。"); super.channelConnected(ctx, e); System.out.println("\n请输入要发送的信息:"); e.getChannel().write(sin.readLine()); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{ if (e.getMessage() instanceof String) { String message = (String) e.getMessage(); System.out.println(message); System.out.println("\n等待客户端输入。。。"); System.out.println("\n请输入要发送的信息:"); e.getChannel().write(sin.readLine()); } super.messageReceived(ctx, e); } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { e.getCause().printStackTrace(); e.getChannel().close(); } }
- netty初析
- Netty
- Netty
- Netty
- Netty
- Netty
- Netty
- netty
- netty
- netty
- Netty
- Netty
- Netty
- Netty
- netty
- Netty
- Netty
- netty
- 整数型 基础知识
- 播放音乐,声音
- swift与OC之间不得不知道的21点
- 【bzoj1015】【JSOI2008】【星球大战】【starwar】【并查集】
- jQuery 学习笔记
- netty初析
- ViewPager无限自动轮播
- 如何使用抓包工具抓包,分析日志。
- 傅立叶变换物理意义解析进阶
- Spring Security 和 Angular JS(1)
- (4)LoadRuner性能测试之内存分析方法及步骤(Windows)
- android源码解析之(二)-->异步消息机制
- git 添加ssh key
- 深入理解为什么Java中方法内定义的内部类可以访问方法中的局部变量