Netty示例
一,服务端
** * 测试Netty类库:服务端代码 * Created by LiuHuiChao on 2016/10/24. */ public class NettyServerTest { private int port; public NettyServerTest(int port){ this.port=port; } /** * EventLoopGroup 是用来处理I/O操作的多线程事件循环器, * Netty提供了许多不同的EventLoopGroup的实现用来处理不同传输协议。 * * * @throws Exception */ public void run() throws Exception{ //一旦 boss 接收到连接,就会把连接信息注册到worker上面 EventLoopGroup bossGroup=new NioEventLoopGroup();//用来接收进来的连接 EventLoopGroup workerGroup=new NioEventLoopGroup();//用来处理已经被接收的连接 System.out.println("准备运行端口:"+port); try{ //ServerBootstrap是一个启动NIO服务的辅助启动类,可以在这个服务中直接使用CChannel ServerBootstrap serverBootstrap=new ServerBootstrap(); serverBootstrap=serverBootstrap.group(bossGroup,workerGroup);//这一步是必须的 serverBootstrap=serverBootstrap.channel(NioServerSocketChannel.class); /* * 这里的事件处理类经常会被用来处理一个最近的已经接收的Channel。 * ChannelInitializer是一个特殊的处理类, * 他的目的是帮助使用者配置一个新的Channel。 * 也许你想通过增加一些处理类比如NettyServerHandler来配置一个新的Channel * 或者其对应的ChannelPipeline来实现你的网络程序。 * 当你的程序变的复杂时,可能你会增加更多的处理类到pipline上, * 然后提取这些匿名类到最顶层的类上。 */ serverBootstrap=serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //socketChannel.pipeline().addLast(new DiscardServerHandler()); socketChannel.pipeline().addLast(new TimeServerHandler()); } }); /** * 可以设置这里指定的通道实现配置参数 * 我们正在写一个TCP/IP的服务端 * 因此我们被允许设置socket的参数选项比如tcpNoDelay,keepAlive */ serverBootstrap=serverBootstrap.option(ChannelOption.SO_BACKLOG,128); serverBootstrap=serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE,true); /** * 绑定端口并启动区接收进来的连接 */ ChannelFuture f=serverBootstrap.bind(port).sync(); f.channel().closeFuture().sync();//这里会一直等待,知道socket被关闭 }catch (Exception e){ }finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if(args.length>0){ port=Integer.parseInt(args[0]); }else{ port=8088; } new NettyServerTest(port).run(); } }
/** * Created by LiuHuiChao on 2016/10/24. */ public class TimeServerHandler extends ChannelHandlerAdapter { /** * 为了发送一个新的消息,我们需要分配一个包含这个消息的新的缓冲。 * 因为我们需要写入一个32位的整数,因此我们需要一个至少有4个字节的ByteBuf。 * 通过ChannelHandlerContext.alloc()得到一个当前的ByteBufAllocator, * 然后分配一个新的缓冲。 */ @Override public void channelActive(final ChannelHandlerContext ctx) throws Exception { final ByteBuf time=ctx.alloc().buffer(4); time.writeInt((int) (System.currentTimeMillis() / 1000L + 2208988800L)); /*** * 和往常一样我们需要编写一个构建好的消息 * 。但是等一等,flip在哪?难道我们使用NIO发送消息时不是调用java.nio.ByteBuffer.flip()吗? * ByteBuf之所以没有这个方法因为有两个指针, * 一个对应读操作一个对应写操作。 * 当你向ByteBuf里写入数据的时候写指针的索引就会增加, * 同时读指针的索引没有变化。 * 读指针索引和写指针索引分别代表了消息的开始和结束。 * 比较起来,NIO缓冲并没有提供一种简洁的方式来计算出消息内容的开始和结尾, * 除非你调用flip方法。 * 当你忘记调用flip方法而引起没有数据或者错误数据被发送时, * 你会陷入困境。这样的一个错误不会发生在Netty上, * 因为我们对于不同的操作类型有不同的指针。 * 你会发现这样的使用方法会让你过程变得更加的容易, * 因为你已经习惯一种没有使用flip的方式。 * 另外一个点需要注意的是ChannelHandlerContext.write()(和writeAndFlush())方法会返回一个ChannelFuture对象, * 一个ChannelFuture代表了一个还没有发生的I/O操作。 * 这意味着任何一个请求操作都不会马上被执行, * 因为在Netty里所有的操作都是异步的。 * 因此你需要在write()方法返回的ChannelFuture完成后调用close()方法, * 然后当他的写操作已经完成他会通知他的监听者。 */ final ChannelFuture f=ctx.writeAndFlush(time); /** * 当一个写请求已经完成是如何通知到我们? * 这个只需要简单地在返回的ChannelFuture上增加一个ChannelFutureListener。 * 这里我们构建了一个匿名的ChannelFutureListener类用来在操作完成时关闭Channel。 */ f.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { assert f==channelFuture; ctx.close();//close方法也可能不会里面关闭,会返回一个ChannelFuture } }); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
二,客户端
/** * Created by LiuHuiChao on 2016/10/24. */ public class TimeClient { public static void main(String[] args) throws Exception { String host="127.0.0.1"; int port=8088; EventLoopGroup workerGroup=new NioEventLoopGroup(); try{ /** * 如果只指定了一个EventLoopGroup, * 那它就会作为boss线程,也会作为worker线程 * 尽管客户端不需要boss线程 */ Bootstrap b=new Bootstrap(); b.group(workerGroup); /** * 代替NioServerSocketChannel的是NioSocketChannel,这个类在客户端channel被创建时候调用 */ b.channel(NioSocketChannel.class); b.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new TimeClientHandler()); } }); ChannelFuture f=b.connect(host,port).sync();//用connect方法替代bind方法 f.channel().closeFuture().sync();//等到运行结束,关闭 }finally { workerGroup.shutdownGracefully(); } } }
/** * Created by LiuHuiChao on 2016/10/24. */ public class TimeClientHandler extends ChannelHandlerAdapter { private ByteBuf buf; /** * 开始处理的时候触发 * @param ctx * @throws Exception */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { buf=ctx.alloc().buffer(4);//分配4个字节的空间给ByteBuf } /** * 处理结束的时候触发 * @param ctx * @throws Exception */ @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { buf.release();//释放ByteBuf的空间 buf=null; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf m=(ByteBuf) msg; buf.writeBytes(m); m.release(); if(buf.readableBytes()>=4){ long currentTimeMillis=(buf.readInt() - 2208988800L) * 1000L; System.out.println(new Date(currentTimeMillis)); ctx.close(); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
(⊙o⊙)…先跑跑。。有点儿困了
Netty示例的更多相关文章
- netty 入门二 (传输bytebuf 或者pojo)
基于流的数据传输:在基于流的传输(如TCP / IP)中,接收的数据被存储到套接字接收缓冲器中. 不幸的是,基于流的传输的缓冲区不是数据包的队列,而是字节队列. 这意味着,即使您将两个消息作为两个独立 ...
- Netty 核心组件 EventLoop 源码解析
前言 在前文 Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23) 中,我们分析了整个服务器端的启动过程.在那篇文章中,我们重点关注了启动过程,而在启动过程中对核心组件并没有进行详细介绍 ...
- Netty 入门初体验
Netty简介 Netty是一款异步的事件驱动的网络应用程序框架,支持快速开发可维护的高性能的面向协议的服务器和客户端.Netty主要是对java 的 nio包进行的封装 为什么要使用 Netty 上 ...
- Netty快速入门(10)Reactor与Netty
Reactor模式 Reactor是1995年由道格拉斯提出的一种高性能网络编程模式.由于好多年了,当时的一些概念与现在略有不同,reactor模式在网络编程中是非常重要的,可以说是NIO框架的典型模 ...
- netty 4.x用户使用指南
引言 问题 现在我们使用通用的应用程序或库来相互通信.例如,我们经常使用HTTP客户机从web服务器检索信息,并通过web服务调用远程过程调用.然而,通用协议或其实现有时不能很好地进行扩展.这就像我们 ...
- Netty之旅二:口口相传的高性能Netty到底是什么?
高清思维导图原件(xmind/pdf/jpg)可以关注公众号:一枝花算不算浪漫 回复netty01即可. 前言 上一篇文章讲了NIO相关的知识点,相比于传统IO,NIO已经做得很优雅了,为什么我们还要 ...
- 深入了解Netty【六】Netty工作原理
引言 前面学习了NIO与零拷贝.IO多路复用模型.Reactor主从模型. 服务器基于IO模型管理连接,获取输入数据,又基于线程模型,处理请求. 下面来学习Netty的具体应用. 1.Netty线程模 ...
- 网络编程Netty入门:Netty的启动过程分析
目录 Netty的启动过程 Bootstrap 服务端的启动 客户端的启动 TCP粘包.拆包 图示 简单的例子 Netty编解码框架 Netty解码器 ByteToMessageDecoder实现类 ...
- Netty4.x中文教程系列(三) Hello World !详解
Netty 中文教程 (二) Hello World !详解 上一篇文章,笔者提供了一个Hello World 的Netty示例. 时间过去了这么久,准备解释一下示例代码. 1.HelloServer ...
随机推荐
- C#检验IIS版本、SQL Server版本、SilverLight版本
之前做一个小项目,使用C#检验这些软件的版本,到处找了一些代码,也能作用,记录一下,以防以后用到. 一.检验IIS版本 public static bool checkIIS(string destV ...
- JavaScript的DOM_获取和操作层次节点
一.层次节点的概述 节点的层次结构可以划分为:父节点与子节点.兄弟节点这两种.当我们获取其中一个元素节点的时候,就可以使用层次节点属性来获取它相关层次的节点. 二.childNodes 属性 chil ...
- Yii: 扩展CGridView增加导出CSV功能
Yii提供的CGridView组件没有内置数据导出功能,不过我们可以通过扩展该组件来添加该功能. 具体方法如下: 1.首先派生一个子类,添加一个action成员,在该视图的init函数中判断是浏览动作 ...
- PHP----预定义数组
预定义数组 超全局数组 <?php /* 预定义数组: * 自动全局变量---超全局数组 * * 1.包含了来自WEB服务器,客户端,运行环境和用户输入的数据 * 2.这些数组比 ...
- 解决 git pull 报错 fatal: refusing to merge unrelated histories
我在Github新建一个仓库,写了License,然后把本地一个写了很久仓库上传. 先pull,因为两个仓库不同,发现refusing to merge unrelated histories,无法p ...
- mac无法使用80端口问题
前言:在mac os中,非root用户是无法使用小于1024的常用端口的.如果开发中需要用到80端口, 就要设置端口转发. hosts文件介绍(1)hosts文件是将域名和IP地址建立映射关系的系统文 ...
- HTML5对表单的一些有意思的改进
HTML5对表单进行了许多的改进,在这篇文章中,我选择了其中个人认为很有趣的三个变化:自动聚焦,对button元素的改进,把表单元素与非父元素的form表单挂钩进行简单的介绍. 1. 自动聚焦 自动聚 ...
- 【题解】洛谷P1351 [NOIP2014TG] 联合权值(树形结构+DFS)
题目来源:洛谷P1351 思路 由题意可得图为一棵树 在一棵树上距离为2的两个点有两种情况 当前点与其爷爷 当前点的两个儿子 当情况为当前点与其爷爷时比较好操作 只需要在传递时不仅传递父亲 还传递爷爷 ...
- 微信小程序的postMessage不实时?
最近在开发小程序的时候用到了wx.postMessage()这个API,在使用前我一直认为wx.postMessage()可以在小程序和H5中实时的传递信息,可以依靠这个API开发一个小程序的brid ...
- Node.js_06 express
一.初探 1 express是什么 Express.js 框架是目前最流行的node.js后端框架之一, 相当于jQuery和js之间的关系; Express 不对 Node.js 已有的特性进行二次 ...