Netty入门官方例子

您所在的位置:网站首页 netty应用案例 Netty入门官方例子

Netty入门官方例子

2023-11-05 04:35| 来源: 网络整理| 查看: 265

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

一.jar包 io.netty netty-all 4.1.6.Final 二.DEMO

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

第一步编写DiscardServerHandler类:

package io.netty.example.discard; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; //ChannelInboundHandlerAdapter实现自ChannelInboundHandler //ChannelInboundHandler提供了不同的事件处理方法你可以重写 public class DiscardServerHandler extends ChannelInboundHandlerAdapter { /* * @作者:CJY * @说明:该方法用于接收从客户端接收的信息 * @时间:2017-4-2下午12:25:05 * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object) * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //Discard the received data silently //ByteBuf是一个引用计数对象实现ReferenceCounted,他就是在有对象引用的时候计数+1,无的时候计数-1,当为0对象释放内存 ByteBuf in=(ByteBuf)msg; try { while(in.isReadable()){ System.out.println((char)in.readByte()); System.out.flush(); } } finally { ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }

第二步编写DiscardServer:

package io.netty.example.discard; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class DiscardServer { private int port; public DiscardServer(int port){ this.port = port; } public void run() throws Exception{ //Group:群组,Loop:循环,Event:事件,这几个东西联在一起,相比大家也大概明白它的用途了。 //Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期。 //NioEventLoopGroup是一个处理I/O操作的多线程事件循环 //bossGroup作为boss,接收传入连接 //因为bossGroup仅接收客户端连接,不做复杂的逻辑处理,为了尽可能减少资源的占用,取值越小越好 EventLoopGroup bossGroup=new NioEventLoopGroup(1); //workerGroup作为worker,处理boss接收的连接的流量和将接收的连接注册进入这个worker EventLoopGroup workerGroup=new NioEventLoopGroup(); try { //ServerBootstrap负责建立服务端 //你可以直接使用Channel去建立服务端,但是大多数情况下你无需做这种乏味的事情 ServerBootstrap b=new ServerBootstrap(); b.group(bossGroup, workerGroup) //指定使用NioServerSocketChannel产生一个Channel用来接收连接 .channel(NioServerSocketChannel.class) //ChannelInitializer用于配置一个新的Channel //用于向你的Channel当中添加ChannelInboundHandler的实现 .childHandler(new ChannelInitializer() { public void initChannel(SocketChannel ch) throws Exception { //ChannelPipeline用于存放管理ChannelHandel //ChannelHandler用于处理请求响应的业务逻辑相关代码 ch.pipeline().addLast(new DiscardServerHandler()); }; }) //对Channel进行一些配置 //注意以下是socket的标准参数 //BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。 //Option是为了NioServerSocketChannel设置的,用来接收传入连接的 .option(ChannelOption.SO_BACKLOG, 128) //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。 //childOption是用来给父级ServerChannel之下的Channels设置参数的 .childOption(ChannelOption.SO_KEEPALIVE, true); // Bind and start to accept incoming connections. ChannelFuture f=b.bind(port).sync(); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to gracefully // shut down your server. //sync()会同步等待连接操作结果,用户线程将在此wait(),直到连接操作完成之后,线程被notify(),用户代码继续执行 //closeFuture()当Channel关闭时返回一个ChannelFuture,用于链路检测 f.channel().closeFuture().sync(); }finally{ //资源优雅释放 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { int port=8088; try { new DiscardServer(port).run(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 里面的具体的类在注释当中进行了说明这里就不在一个一个罗列了,目前也是在初步学习阶段,所以如果有不对的也希望大神指正。 三.测试

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

四.ECHO协议的DEMO

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

第一步编写EchoServerHandler:

package io.netty.example.echo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * @作者:CJY * @说明:这个是用来实现ECHO协议,这个协议的作用就是将客户端输入的信息全部返回 * @时间:2017-4-8下午12:07:50 */ public class EchoServerHandler extends ChannelInboundHandlerAdapter { /* * @作者:CJY * @说明:该方法用于接收从客户端接收的信息 * @时间:2017-4-8下午12:08:51 * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object) * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //ChannelHandlerContext提供各种不同的操作用于触发不同的I/O时间和操作 //调用write方法来逐字返回接收到的信息 //这里我们不需要在DISCARD例子当中那样调用释放,因为Netty会在写的时候自动释放 //只调用write是不会释放的,它会缓存,直到调用flush ctx.write(msg); ctx.flush(); //你可以直接使用writeAndFlush(msg) //ctx.writeAndFlush(msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } 第二步编写EchoServer: package io.netty.example.echo; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class EchoServer { private int port; public EchoServer(int port){ this.port = port; } public void run() throws Exception{ //NioEventLoopGroup是一个处理I/O操作的多线程事件循环 //bossGroup作为boss,接收传入连接 //bossGroup只负责接收客户端的连接,不做复杂操作,为了减少资源占用,取值越小越好 //Group:群组,Loop:循环,Event:事件,这几个东西联在一起,相比大家也大概明白它的用途了。 //Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期。 EventLoopGroup bossGroup=new NioEventLoopGroup(1); //workerGroup作为worker,处理boss接收的连接的流量和将接收的连接注册进入这个worker EventLoopGroup workerGroup=new NioEventLoopGroup(); try { //ServerBootstrap负责建立服务端 //你可以直接使用Channel去建立服务端,但是大多数情况下你无需做这种乏味的事情 ServerBootstrap b=new ServerBootstrap(); b.group(bossGroup, workerGroup) //指定使用NioServerSocketChannel产生一个Channel用来接收连接 .channel(NioServerSocketChannel.class) //ChannelInitializer用于配置一个新的Channel //用于向你的Channel当中添加ChannelInboundHandler的实现 .childHandler(new ChannelInitializer() { public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); }; }) //对Channel进行一些配置 //注意以下是socket的标准参数 //BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。 //Option是为了NioServerSocketChannel设置的,用来接收传入连接的 .option(ChannelOption.SO_BACKLOG, 128) //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。 //childOption是用来给父级ServerChannel之下的Channels设置参数的 .childOption(ChannelOption.SO_KEEPALIVE, true); // Bind and start to accept incoming connections. ChannelFuture f=b.bind(port).sync(); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to gracefully // shut down your server. //sync()会同步等待连接操作结果,用户线程将在此wait(),直到连接操作完成之后,线程被notify(),用户代码继续执行 //closeFuture()当Channel关闭时返回一个ChannelFuture,用于链路检测 f.channel().closeFuture().sync(); }finally{ //资源优雅释放 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { int port=8088; try { new EchoServer(port).run(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

测试如上不再赘述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3