Netty入门官方例子

本人开启的第一篇博客,正好最近辞职在家,学习分布式,正好看到Netty 是一个基于NIO的客户、服务器端编程框架,所以本着学习的态度去官网看了一下,官网例子,本着以后可以翻出来再看看的心态,把官网的第一个例子贴出来,也希望自己以后有一个可以复习的地方,第一次使用博客功能,还有很多不懂的地方

一.jar包

<!-- Netty开始 -->

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->

<dependency>

<groupId>io.netty</groupId>

<artifactId>netty-all</artifactId>

<version>4.1.6.Final</version>

</dependency>

<!-- Netty结束 -->

二.DEMO

官方并没有使用Hello World来作为一个例子,而是采用RFC的DISCARD,这个协议定义了就是接收到请求后什么也不干。

第一步编写DiscardServerHandler类:

 
  1. package io.netty.example.discard;

  2.  
  3. import io.netty.buffer.ByteBuf;

  4. import io.netty.channel.ChannelHandlerContext;

  5. import io.netty.channel.ChannelInboundHandlerAdapter;

  6. import io.netty.util.ReferenceCountUtil;

  7. //ChannelInboundHandlerAdapter实现自ChannelInboundHandler

  8. //ChannelInboundHandler提供了不同的事件处理方法你可以重写

  9. public class DiscardServerHandler extends ChannelInboundHandlerAdapter {

  10. /*

  11. * @作者:CJY

  12. * @说明:该方法用于接收从客户端接收的信息

  13. * @时间:2017-4-2下午12:25:05

  14. * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object)

  15. * @param ctx

  16. * @param msg

  17. * @throws Exception

  18. */

  19. @Override

  20. public void channelRead(ChannelHandlerContext ctx, Object msg)

  21. throws Exception {

  22. //Discard the received data silently

  23. //ByteBuf是一个引用计数对象实现ReferenceCounted,他就是在有对象引用的时候计数+1,无的时候计数-1,当为0对象释放内存

  24. ByteBuf in=(ByteBuf)msg;

  25. try {

  26. while(in.isReadable()){

  27. System.out.println((char)in.readByte());

  28. System.out.flush();

  29. }

  30. } finally {

  31. ReferenceCountUtil.release(msg);

  32. }

  33. }

  34.  
  35. @Override

  36. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)

  37. throws Exception {

  38. cause.printStackTrace();

  39. ctx.close();

  40. }

  41. }


 

第二步编写DiscardServer:

 
  1. package io.netty.example.discard;

  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. import io.netty.channel.nio.NioEventLoopGroup;

  9. import io.netty.channel.socket.SocketChannel;

  10. import io.netty.channel.socket.nio.NioServerSocketChannel;

  11.  
  12. public class DiscardServer {

  13. private int port;

  14. public DiscardServer(int port){

  15. this.port = port;

  16. }

  17.  
  18. public void run() throws Exception{

  19. //Group:群组,Loop:循环,Event:事件,这几个东西联在一起,相比大家也大概明白它的用途了。

  20. //Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期。

  21. //NioEventLoopGroup是一个处理I/O操作的多线程事件循环

  22. //bossGroup作为boss,接收传入连接

  23. //因为bossGroup仅接收客户端连接,不做复杂的逻辑处理,为了尽可能减少资源的占用,取值越小越好

  24. EventLoopGroup bossGroup=new NioEventLoopGroup(1);

  25. //workerGroup作为worker,处理boss接收的连接的流量和将接收的连接注册进入这个worker

  26. EventLoopGroup workerGroup=new NioEventLoopGroup();

  27. try {

  28. //ServerBootstrap负责建立服务端

  29. //你可以直接使用Channel去建立服务端,但是大多数情况下你无需做这种乏味的事情

  30. ServerBootstrap b=new ServerBootstrap();

  31. b.group(bossGroup, workerGroup)

  32. //指定使用NioServerSocketChannel产生一个Channel用来接收连接

  33. .channel(NioServerSocketChannel.class)

  34. //ChannelInitializer用于配置一个新的Channel

  35. //用于向你的Channel当中添加ChannelInboundHandler的实现

  36. .childHandler(new ChannelInitializer<SocketChannel>() {

  37. public void initChannel(SocketChannel ch) throws Exception {

  38. //ChannelPipeline用于存放管理ChannelHandel

  39. //ChannelHandler用于处理请求响应的业务逻辑相关代码

  40. ch.pipeline().addLast(new DiscardServerHandler());

  41. };

  42. })

  43. //对Channel进行一些配置

  44. //注意以下是socket的标准参数

  45. //BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。

  46. //Option是为了NioServerSocketChannel设置的,用来接收传入连接的

  47. .option(ChannelOption.SO_BACKLOG, 128)

  48. //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。

  49. //childOption是用来给父级ServerChannel之下的Channels设置参数的

  50. .childOption(ChannelOption.SO_KEEPALIVE, true);

  51. // Bind and start to accept incoming connections.

  52. ChannelFuture f=b.bind(port).sync();

  53. // Wait until the server socket is closed.

  54. // In this example, this does not happen, but you can do that to gracefully

  55. // shut down your server.

  56. //sync()会同步等待连接操作结果,用户线程将在此wait(),直到连接操作完成之后,线程被notify(),用户代码继续执行

  57. //closeFuture()当Channel关闭时返回一个ChannelFuture,用于链路检测

  58. f.channel().closeFuture().sync();

  59. }finally{

  60. //资源优雅释放

  61. bossGroup.shutdownGracefully();

  62. workerGroup.shutdownGracefully();

  63. }

  64. }

  65.  
  66. public static void main(String[] args) {

  67. int port=8088;

  68. try {

  69. new DiscardServer(port).run();

  70. } catch (Exception e) {

  71. // TODO Auto-generated catch block

  72. e.printStackTrace();

  73. }

  74. }

  75. }

里面的具体的类在注释当中进行了说明这里就不在一个一个罗列了,目前也是在初步学习阶段,所以如果有不对的也希望大神指正。

三.测试

打开Window的命令行,输入telnet命令:telnet localhost 8088,如果能够正确连接就代表成功,在新打开的命令窗口随意输入字符,如果在myeclipse当中能够正确输出在console当中,就代表程序正常。

四.ECHO协议的DEMO

ECHO协议,定义了客户端请求啥就返回啥

第一步编写EchoServerHandler:

 
  1. package io.netty.example.echo;

  2.  
  3. import io.netty.channel.ChannelHandlerContext;

  4. import io.netty.channel.ChannelInboundHandlerAdapter;

  5.  
  6. /**

  7. * @作者:CJY

  8. * @说明:这个是用来实现ECHO协议,这个协议的作用就是将客户端输入的信息全部返回

  9. * @时间:2017-4-8下午12:07:50

  10. */

  11. public class EchoServerHandler extends ChannelInboundHandlerAdapter {

  12. /*

  13. * @作者:CJY

  14. * @说明:该方法用于接收从客户端接收的信息

  15. * @时间:2017-4-8下午12:08:51

  16. * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object)

  17. * @param ctx

  18. * @param msg

  19. * @throws Exception

  20. */

  21. @Override

  22. public void channelRead(ChannelHandlerContext ctx, Object msg)

  23. throws Exception {

  24. //ChannelHandlerContext提供各种不同的操作用于触发不同的I/O时间和操作

  25. //调用write方法来逐字返回接收到的信息

  26. //这里我们不需要在DISCARD例子当中那样调用释放,因为Netty会在写的时候自动释放

  27. //只调用write是不会释放的,它会缓存,直到调用flush

  28. ctx.write(msg);

  29. ctx.flush();

  30. //你可以直接使用writeAndFlush(msg)

  31. //ctx.writeAndFlush(msg);

  32. }

  33.  
  34. @Override

  35. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)

  36. throws Exception {

  37. cause.printStackTrace();

  38. ctx.close();

  39. }

  40. }


第二步编写EchoServer:

 
  1. package io.netty.example.echo;

  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. import io.netty.channel.nio.NioEventLoopGroup;

  9. import io.netty.channel.socket.SocketChannel;

  10. import io.netty.channel.socket.nio.NioServerSocketChannel;

  11.  
  12. public class EchoServer {

  13. private int port;

  14. public EchoServer(int port){

  15. this.port = port;

  16. }

  17.  
  18. public void run() throws Exception{

  19. //NioEventLoopGroup是一个处理I/O操作的多线程事件循环

  20. //bossGroup作为boss,接收传入连接

  21. //bossGroup只负责接收客户端的连接,不做复杂操作,为了减少资源占用,取值越小越好

  22. //Group:群组,Loop:循环,Event:事件,这几个东西联在一起,相比大家也大概明白它的用途了。

  23. //Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期。

  24. EventLoopGroup bossGroup=new NioEventLoopGroup(1);

  25. //workerGroup作为worker,处理boss接收的连接的流量和将接收的连接注册进入这个worker

  26. EventLoopGroup workerGroup=new NioEventLoopGroup();

  27. try {

  28. //ServerBootstrap负责建立服务端

  29. //你可以直接使用Channel去建立服务端,但是大多数情况下你无需做这种乏味的事情

  30. ServerBootstrap b=new ServerBootstrap();

  31. b.group(bossGroup, workerGroup)

  32. //指定使用NioServerSocketChannel产生一个Channel用来接收连接

  33. .channel(NioServerSocketChannel.class)

  34. //ChannelInitializer用于配置一个新的Channel

  35. //用于向你的Channel当中添加ChannelInboundHandler的实现

  36. .childHandler(new ChannelInitializer<SocketChannel>() {

  37. public void initChannel(SocketChannel ch) throws Exception {

  38. ch.pipeline().addLast(new EchoServerHandler());

  39. };

  40. })

  41. //对Channel进行一些配置

  42. //注意以下是socket的标准参数

  43. //BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。

  44. //Option是为了NioServerSocketChannel设置的,用来接收传入连接的

  45. .option(ChannelOption.SO_BACKLOG, 128)

  46. //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。

  47. //childOption是用来给父级ServerChannel之下的Channels设置参数的

  48. .childOption(ChannelOption.SO_KEEPALIVE, true);

  49. // Bind and start to accept incoming connections.

  50. ChannelFuture f=b.bind(port).sync();

  51. // Wait until the server socket is closed.

  52. // In this example, this does not happen, but you can do that to gracefully

  53. // shut down your server.

  54. //sync()会同步等待连接操作结果,用户线程将在此wait(),直到连接操作完成之后,线程被notify(),用户代码继续执行

  55. //closeFuture()当Channel关闭时返回一个ChannelFuture,用于链路检测

  56. f.channel().closeFuture().sync();

  57. }finally{

  58. //资源优雅释放

  59. bossGroup.shutdownGracefully();

  60. workerGroup.shutdownGracefully();

  61. }

  62. }

  63.  
  64. public static void main(String[] args) {

  65. int port=8088;

  66. try {

  67. new EchoServer(port).run();

  68. } catch (Exception e) {

  69. // TODO Auto-generated catch block

  70. e.printStackTrace();

  71. }

  72. }

  73. }


 

测试如上不再赘述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值