netty入门

本文通过一个简单的例子,来讲解netty最基本的用法。 
  首先,创建工程mynetty,引入netty的依赖包: 
 
Java代码   收藏代码
  1. <dependency>  
  2.     <groupId>io.netty</groupId>  
  3.     <artifactId>netty</artifactId>  
  4.     <version>3.5.6.Final</version>  
  5. </dependency>  

  创建好之后,开始编码: 
1. 新建类NettyServer 
Java代码   收藏代码
  1. package com.netty.intr;  
  2.   
  3. import java.net.InetSocketAddress;  
  4. import java.util.concurrent.Executors;  
  5. import org.jboss.netty.bootstrap.ServerBootstrap;  
  6. import org.jboss.netty.channel.Channel;  
  7. import org.jboss.netty.channel.ChannelHandlerContext;  
  8. import org.jboss.netty.channel.ChannelStateEvent;  
  9. import org.jboss.netty.channel.MessageEvent;  
  10. import org.jboss.netty.channel.SimpleChannelHandler;  
  11. import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;  
  12.   
  13. public class NettyServer {  
  14.     final static int port = 8080;  
  15.   
  16.     public static void main(String[] args) {  
  17.         Server server = new Server();  
  18.         server.config(port);  
  19.         server.start();  
  20.     }  
  21. }  
  22.   
  23. class Server {  
  24.     ServerBootstrap bootstrap;  
  25.     Channel parentChannel;  
  26.     InetSocketAddress localAddress;  
  27.     MyChannelHandler channelHandler = new MyChannelHandler();  
  28.   
  29.     Server() {  
  30.         bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(  
  31.                 Executors.newCachedThreadPool(), Executors  
  32.                         .newCachedThreadPool()));  
  33.         bootstrap.setOption("reuseAddress"true);  
  34.         bootstrap.setOption("child.tcpNoDelay"true);  
  35.         bootstrap.setOption("child.soLinger"2);  
  36.         bootstrap.getPipeline().addLast("servercnfactory", channelHandler);  
  37.     }  
  38.   
  39.     void config(int port) {  
  40.         this.localAddress = new InetSocketAddress(port);  
  41.     }  
  42.   
  43.     void start() {  
  44.         parentChannel = bootstrap.bind(localAddress);  
  45.     }  
  46.   
  47.     class MyChannelHandler extends SimpleChannelHandler {  
  48.   
  49.         @Override  
  50.         public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)  
  51.                 throws Exception {  
  52.             System.out.println("Channel closed " + e);  
  53.         }  
  54.   
  55.         @Override  
  56.         public void channelConnected(ChannelHandlerContext ctx,  
  57.                 ChannelStateEvent e) throws Exception {  
  58.             System.out.println("Channel connected " + e);  
  59.         }  
  60.   
  61.         @Override  
  62.         public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)  
  63.                 throws Exception {  
  64.             try {  
  65.                 System.out.println("New message " + e.toString() + " from "  
  66.                         + ctx.getChannel());  
  67.                 processMessage(e);  
  68.             } catch (Exception ex) {  
  69.                 ex.printStackTrace();  
  70.                 throw ex;  
  71.             }  
  72.         }  
  73.   
  74.         private void processMessage(MessageEvent e) {  
  75.             Channel ch = e.getChannel();  
  76.             ch.write(e.getMessage());  
  77.         }  
  78.     }  
  79. }  

2. 运行程序,打开命令行,输入:telnet 127.0.0.1 8080,在控制台会出现: 
Java代码   收藏代码
  1. Channel connected [id: 0x29b7df26, /127.0.0.1:51554 => /127.0.0.1:8080] CONNECTED: /127.0.0.1:51554  

表示有客户端连接到了server,并且打印出了客户端的信息。 

3. 任意输入一个字符(如:a),在控制台会出现: 
Java代码   收藏代码
  1. New message [id: 0x29b7df26, /127.0.0.1:51554 => /127.0.0.1:8080] RECEIVED: BigEndianHeapChannelBuffer(ridx=0, widx=1, cap=1) from [id: 0x29b7df26, /127.0.0.1:51554 => /127.0.0.1:8080]  

这就意味着Server收到了来自client的message,打印出了客户端信息以及message的基本信息。而在命令行窗口会出现我们刚才输入的字符a。 

4. 当关闭命令行窗口时,控制台会出现: 
Java代码   收藏代码
  1. Channel closed [id: 0x29b7df26, /127.0.0.1:51554 :> /127.0.0.1:8080] CLOSED  

表示连接已经关闭了。 


  从现象到本质,下面来做简单的解释。服务器的主要逻辑都放在类Server中的,所以来看一下该类中是如何启动服务器、接收消息的。 
  首先是构造方法: 
1. 初始化ServerBootstrap,并注入NioServerSocketChannelFactory,用于创建通道(channel)等。从这里可以看出是通过Nio的方式来处理的,factory中放入两个线程池,主要用于接收connect和message。 
Java代码   收藏代码
  1. bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(  
  2.                 Executors.newCachedThreadPool(), Executors  
  3.                         .newCachedThreadPool()));  


2. 为通道以及子通道(带前缀”child.”)设置相关的属性(socket属性),此处暂不详细介绍。 
Java代码   收藏代码
  1. bootstrap.setOption("reuseAddress"true);  
  2. bootstrap.setOption("child.tcpNoDelay"true);  
  3. bootstrap.setOption("child.soLinger"2);  


3. 向ChannelPipline中添加处理器(ChannelHandler),用于处理连接和消息。 
Java代码   收藏代码
  1. bootstrap.getPipeline().addLast("servercnfactory", channelHandler);  

  MyHandler继承了SimpleChannelHandler,并且重写了方法:channelClosed、channelConnected、messageReseived,方法的参数为ChannelHandlerContext和ChannelEvent。ChannelHandlerContext为通道上下文,event中便带有消息和连接的信息。 
  channelConnected方法在接到来自客户端的连接时触发(这里只是打印了收到的连接的信息),所以在执行telnet命令时,看到控制台会有相应的输出。 
  MessageReseived方法在接收到消息是会触发,这里会交给processMessage方法处理,这里只是简单的把接收到的信息写回客户端。所以在命令行窗口中会看到我们写入的字母信息。 
  ChannelClosed方法在关闭连接的时候被调用,当我们关闭命令行窗口的时候,就会看到控制台打印出相应的信息。 
  当然,ChannelHander的接口不止这么三个,除了SimpleChannelHandler以外还有很特殊的实现,这里只做简单介绍。 


  初始化完成之后,我们调用server.config(int port)方法注入需要绑定的端口信息,这里为8080。 

  最后调用server.start()方法,服务器便启动起来了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值