Netty入门实例及分析
2016-01-01 14:50
399 查看
什么是netty?以下是官方文档的简单介绍:
The Netty project is an effort to provide
an asynchronous event-driven network application framework and tools for rapid development of maintainable high performance and high scalability protocol servers and clients. In other words, 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/IP
socket server.
以下写一个简单的实例:
1.client细节分析
ChannelFactory是创建一个通道(和一次详细的通信实体关联如网络套接字)的主要接口。比方NioServerSocketChannelFactory 会创建一个Channel,有基于NIO的服务套接字作为底层的通信实体。一旦一个新的通道创建。那么相应的ChannelPipeline就会開始处理相关的ChannelEvents。
NioClientSocketChannelFactory会创建一个client的基于NIO的SocketChannel。利用非堵塞IO模型来高效处理这些并发的连接。当中有两种类型的线程, boss thread 和 worker thread,每一个NioClientSocketChannelFactory
有一个boss thread。它主要是有请求要发出时试图进行一次连接。连接成功后,将这个连接的通道交付给一个worker thread。接下来这个worker thread 为一个或多个通道运行非堵塞的读写服务。
[align=left]ClientBootstrap仅仅是一个辅助函数,不会分配或者管理不论什么资源,管理资源是由构造器中指定的ChannelFactory完毕的。所以从同一个ChannelFactory衍生出多个ClientBootstrap是能够的。从而为不同的Channel应用不同的设置。connect()方法会依据指定的SocketAddress试图建立连接,假设本地地址没有设置,就会自己主动分配,等价于:[/align]
[align=left]ClientBootstrap b = ....;[/align]
[align=left]b.connect(remoteAddress, b.getOption("localAddress"));[/align]
静态方法 Channels.pipeline(ChannelHandler... handlers)用參数所指定的ChannelHandler 来创建一个新的ChannelPipeline,当然它们是有顺序的,我们也能够自己一个一个的加入。
public static ChannelPipeline pipeline(ChannelHandler...
handlers) {
[align=left] if (handlers == null) {[/align]
[align=left] throw new NullPointerException( "handlers");[/align]
[align=left] }[/align]
[align=left] ChannelPipeline newPipeline = pipeline ();[/align]
for (int i = 0; i < handlers. length;
i ++) {
[align=left] ChannelHandler h = handlers[i];[/align]
[align=left] if (h == null) {[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left] newPipeline.addLast(ConversionUtil. toString(i), h);[/align]
[align=left] }[/align]
[align=left] return newPipeline;[/align]
[align=left] }[/align]
[align=left]2. server端细节分析[/align]
服务器端构建的基本流程和client类似,仅仅是这里的ChannelFactory。Bootstrap 都要满足作为server的特性。
NioServerSocketChannelFactory创建server端的,基于NIO的ServerSocketChannel。仍然是非堵塞模式。
每一个绑定的ServerSocketChannel 有自身的boos thread,比方说打开监听了两个port 80,443。那么就会有两个boss thread,各自负责各自port的连接请求,直到那个port解绑定,然后将接受的连接请求交给worker
thread去处理。
[align=left]这里是面向连接传输的ClientBootstrap 和 ServerBootstrap 。假设想用UDP的话就选 ConnectionlessBootstrap。[/align]
3. ChannelHandler的常见使用方法就会依据详细的事件类型做出详细的处理。牵扯到读写管道。并且有上下流的情况。
[align=left]一个简单的netty样例:[/align]
[align=left]TimeClientl.java[/align]
[align=left]TimeClientHandler.java[/align]
[align=left]TimeServer.java[/align]
[align=left]TimeServerHandler.java[/align]
The Netty project is an effort to provide
an asynchronous event-driven network application framework and tools for rapid development of maintainable high performance and high scalability protocol servers and clients. In other words, 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/IP
socket server.
以下写一个简单的实例:
1.client细节分析
ChannelFactory是创建一个通道(和一次详细的通信实体关联如网络套接字)的主要接口。比方NioServerSocketChannelFactory 会创建一个Channel,有基于NIO的服务套接字作为底层的通信实体。一旦一个新的通道创建。那么相应的ChannelPipeline就会開始处理相关的ChannelEvents。
NioClientSocketChannelFactory会创建一个client的基于NIO的SocketChannel。利用非堵塞IO模型来高效处理这些并发的连接。当中有两种类型的线程, boss thread 和 worker thread,每一个NioClientSocketChannelFactory
有一个boss thread。它主要是有请求要发出时试图进行一次连接。连接成功后,将这个连接的通道交付给一个worker thread。接下来这个worker thread 为一个或多个通道运行非堵塞的读写服务。
[align=left]ClientBootstrap仅仅是一个辅助函数,不会分配或者管理不论什么资源,管理资源是由构造器中指定的ChannelFactory完毕的。所以从同一个ChannelFactory衍生出多个ClientBootstrap是能够的。从而为不同的Channel应用不同的设置。connect()方法会依据指定的SocketAddress试图建立连接,假设本地地址没有设置,就会自己主动分配,等价于:[/align]
[align=left]ClientBootstrap b = ....;[/align]
[align=left]b.connect(remoteAddress, b.getOption("localAddress"));[/align]
静态方法 Channels.pipeline(ChannelHandler... handlers)用參数所指定的ChannelHandler 来创建一个新的ChannelPipeline,当然它们是有顺序的,我们也能够自己一个一个的加入。
public static ChannelPipeline pipeline(ChannelHandler...
handlers) {
[align=left] if (handlers == null) {[/align]
[align=left] throw new NullPointerException( "handlers");[/align]
[align=left] }[/align]
[align=left] ChannelPipeline newPipeline = pipeline ();[/align]
for (int i = 0; i < handlers. length;
i ++) {
[align=left] ChannelHandler h = handlers[i];[/align]
[align=left] if (h == null) {[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left] newPipeline.addLast(ConversionUtil. toString(i), h);[/align]
[align=left] }[/align]
[align=left] return newPipeline;[/align]
[align=left] }[/align]
[align=left]2. server端细节分析[/align]
服务器端构建的基本流程和client类似,仅仅是这里的ChannelFactory。Bootstrap 都要满足作为server的特性。
NioServerSocketChannelFactory创建server端的,基于NIO的ServerSocketChannel。仍然是非堵塞模式。
每一个绑定的ServerSocketChannel 有自身的boos thread,比方说打开监听了两个port 80,443。那么就会有两个boss thread,各自负责各自port的连接请求,直到那个port解绑定,然后将接受的连接请求交给worker
thread去处理。
[align=left]这里是面向连接传输的ClientBootstrap 和 ServerBootstrap 。假设想用UDP的话就选 ConnectionlessBootstrap。[/align]
3. ChannelHandler的常见使用方法就会依据详细的事件类型做出详细的处理。牵扯到读写管道。并且有上下流的情况。
[align=left]一个简单的netty样例:[/align]
[align=left]TimeClientl.java[/align]
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.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; public class TimeClient { public static void main(String[] args) { String host = args[0]; int port = Integer.parseInt(args[1]); ChannelFactory factory = new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ClientBootstrap bootstrap = new ClientBootstrap(factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new TimeClientHandler2()); } }); bootstrap.connect(new InetSocketAddress(host, port)); // } }
[align=left]TimeClientHandler.java[/align]
import java.util.Date; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; public class TimeClientHandler extends SimpleChannelHandler{ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { ChannelBuffer buffer = (ChannelBuffer)e.getMessage(); long currentTimeMills = buffer.readInt() * 1000L; System.out.println(new Date(currentTimeMills)); e.getChannel().close(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { e.getCause().printStackTrace(); Channel c = e.getChannel(); c.close(); } }
[align=left]TimeServer.java[/align]
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.group.ChannelGroup; import org.jboss.netty.channel.group.ChannelGroupFuture; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; public class TimeServer { public static ChannelGroup allChannels = new DefaultChannelGroup("time-server"); public static void main(String[] args) { ChannelFactory factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap(factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new TimeServerHandler2(), new TimeEncoder()); } }); bootstrap.setOption("reuseAddr", true); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); Channel channel = bootstrap.bind(new InetSocketAddress(8080)); allChannels.add(channel); //waitForShutdownCommand(); this is a imaginary logic:for instance //when there is accepted connection we close this server ; if(allChannels.size() >=2){ ChannelGroupFuture f = allChannels.close(); f.awaitUninterruptibly(); factory.releaseExternalResources(); } } }
[align=left]TimeServerHandler.java[/align]
import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.SimpleChannelHandler; public class TimeServerHandler extends SimpleChannelHandler{ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { Channel ch = e.getChannel(); ChannelBuffer time = ChannelBuffers.buffer(4); //sizeof int time.writeInt((int)(System.currentTimeMillis()/1000L + 2208988800L)); ChannelFuture cf = ch.write(time); cf.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { Channel ch = future.getChannel(); ch.close(); } }); } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { e.getCause().printStackTrace(); Channel c = e.getChannel(); c.close(); } }
相关文章推荐
- 航电acm--2107
- 《挑战程序设计竞赛》3.2.5 常用技巧-坐标离散化 AOJ0531(1RE)
- 移动端适配
- 在windows上部署使用Redis
- UDP Socket出现10054错误码的解决方法
- 《挑战程序设计竞赛》3.2.4 常用技巧-折半枚举 POJ2785 3977 2549
- C 程序的执行过程 - 2016.01.01
- 航电acm--2101
- 错误消息: 为了配置 TCP/IP,必须安装并启用的网络适配器
- HDU2578 Dating with girls(1)(二分)
- 《挑战程序设计竞赛》3.2.3 常用技巧-弹性碰撞 POJ3684 2674
- 《挑战程序设计竞赛》3.2.2 常用技巧-反转 POJ3276 3279 3185 1222
- 航电acm--2123
- c++ 类型萃取(模板类型 运用)
- ls命令的简单实现
- 【FLASH】flash发布APK遇到问题
- LeetCode Count Complete Tree Nodes
- 实战—详解—阿里云服务器lvm扩容
- JavaScript中字符串String的常用方法总结
- 页面加载特效与Xftp的问题