ImageVerifierCode 换一换
格式:DOCX , 页数:36 ,大小:34.19KB ,
资源ID:11772328      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11772328.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Netty 中文技术文档.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Netty 中文技术文档.docx

1、Netty 中文技术文档本指南对Netty 进行了介绍并指出其意义所在。1. 问题现在,我们使用适合一般用途的应用或组件来和彼此通信。例如,我们常常使用一个HTTP客户端从远程服务器获取信息或者通过webservices进行远程方法的调用。然而,一个适合普通目的的协议或其实现并不具备其规模上的扩展性。例如,我们无法使用一个普通的HTTP服务器进行大型文件,电邮信息的交互,或者处理金融信息和多人游戏数据那种要求准实时消息传递的应用场景。因此,这些都要求使用一个适用于特殊目的并经过高度优化的协议实现。例如,你可能想要实现一个对基于AJAX的聊天应用,媒体流或大文件传输进行过特殊优化的HTTP服务器

2、。你甚至可能想去设计和实现一个全新的,特定于你的需求的通信协议。另一种无法避免的场景是你可能不得不使用一种专有的协议和原有系统交互。在这种情况下,你需要考虑的是如何能够快速的开发出这个协议的实现并且同时还没有牺牲最终应用的性能和稳定性。2. 方案Netty 是一个异步的,事件驱动的网络编程框架和工具,使用Netty可以快速开发出可维护的,高性能、高扩展能力的协议服务及其客户端应用。也就是说,Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,

3、TCP和UDP的socket服务开发。快速和简单并不意味着会让你的最终应用产生维护性或性能上的问题。Netty是一个吸收了多种协议的实现经验,这些协议包括FTP,SMPT,HTTP,各种二进制,文本协议,并经过相当精心设计的项目,最终,Netty成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。一些用户可能找到了某些同样声称具有这些特性的编程框架,因此你们可能想问Netty 又有什么不一样的地方。这个问题的答案是Netty项目的设计哲学。从创立之初,无论是在API还是在其实现上Netty都致力于为你提供最为舒适的使用体验。虽然这并不是显而易见的,但你终将会认识到这

4、种设计哲学将令你在阅读本指南和使用Netty时变得更加得轻松和容易。第一章. 开始这一章节将围绕Netty的核心结构展开,同时通过一些简单的例子可以让你更快的了解Netty的使用。当你读完本章,你将有能力使用Netty完成客户端和服务端的开发。如果你更喜欢自上而下式的学习方式,你可以首先完成 第二章:架构总览 的学习,然后再回到这里。1.1. 开始之前运行本章示例程序的两个最低要求是:最新版本的Netty程序以及JDK 1.5或更高版本。最新版本的Netty程序可在项目下载页下载。下载正确版本的JDK,请到你偏好的JDK站点下载。这就已经足够了吗?实际上你会发现,这两个条件已经足够你完成任何协

5、议的开发了。如果不是这样,请联系Netty项目社区,让我们知道还缺少了什么。最终但不是至少,当你想了解本章所介绍的类的更多信息时请参考API手册。为方便你的使用,这篇文档中所有的类名均连接至在线API手册。此外,如果本篇文档中有任何错误信息,无论是语法错误,还是打印排版错误或者你有更好的建议,请不要顾虑,立即联系Netty项目社区 。1.2. 抛弃协议服务在这个世界上最简化的协议不是Hello,world!而是抛弃协议 。这是一种丢弃接收到的任何数据并不做任何回应的协议。实现抛弃协议(DISCARDprotocol),你仅需要忽略接受到的任何数据即可。让我们直接从处理器(handler)实现开

6、始,这个处理器处理Netty的所有I/O事件。package ty.example.discard; ChannelPipelineCoverage(all)1 public class DiscardServerHandler extends SimpleChannelHandler 2 Override public void messageReceived(ChannelHandlerContext ctx,MessageEvent e) 3 Override public void exceptionCaught(ChannelHandlerContext ctx,ExceptionE

7、vent e) 4 e.getCause().printStackTrace(); Channel ch = e.getChannel(); ch.close(); Override public void exceptionCaught(ChannelHandlerContext ctx,ExceptionEvent e) 4 e.getCause().printStackTrace(); Channel ch = e.getChannel(); ch.close(); 代码说明1)ChannelPipelineCoverage注解了一种处理器类型,这个注解标示了一个处理器是否可被多个Cha

8、nnel通道共享(同时关联着ChannelPipeline)。DiscardServerHandler没有处理任何有状态的信息,因此这里的注解是all。2)DiscardServerHandler继承了SimpleChannelHandler,这也是一个ChannelHandler的实现。SimpleChannelHandler提供了多种你可以重写的事件处理方法。目前直接继承SimpleChannelHandler已经足够了,并不需要你完成一个自己的处理器接口。3)我们这里重写了messageReceived事件处理方法。这个方法由一个接收了客户端传送数据的MessageEvent事件调用。在

9、这个例子中,我们忽略接收到的任何数据,并以此来实现一个抛弃协议(DISCARD protocol)。4)exceptionCaught事件处理方法由一个ExceptionEvent异常事件调用,这个异常事件起因于Netty的I/O异常或一个处理器实现的内部异常。多数情况下,捕捉到的异常应当被记录下来,并在这个方法中关闭这个channel通道。当然处理这种异常情况的方法实现可能因你的实际需求而有所不同,例如,在关闭这个连接之前你可能会发送一个包含了错误码的响应消息。目前进展不错,我们已经完成了抛弃协议服务器的一半开发工作。下面要做的是完成一个可以启动这个包含DiscardServerHandle

10、r处理器服务的主方法。package ty.example.discard; import .InetSocketAddress; import java.util.concurrent.Executors; public class DiscardServer public static void main(String args) throws Exception ChannelFactory factory = new NioServerSocketChannelFactory ( Executors.newCachedThreadPool(), Executors.newCachedT

11、hreadPool(); ServerBootstrap bootstrap = new ServerBootstrap (factory); DiscardServerHandler handler = new DiscardServerHandler(); ChannelPipeline pipeline = bootstrap.getPipeline(); pipeline.addLast(handler, handler); bootstrap.setOption(child.tcpNoDelay, true); bootstrap.setOption(child.keepAlive,

12、 true); bootstrap.bind(new InetSocketAddress(8080); 代码说明1)ChannelFactory 是一个创建和管理Channel通道及其相关资源的工厂接口,它处理所有的I/O请求并产生相应的I/OChannelEvent通道事件。Netty 提供了多种 ChannelFactory实现。这里我们需要实现一个服务端的例子,因此我们使用NioServerSocketChannelFactory实现。另一件需要注意的事情是这个工厂并自己不负责创建I/O线程。你应当在其构造器中指定该工厂使用的线程池,这样做的好处是你获得了更高的控制力来管理你的应用环境中

13、使用的线程,例如一个包含了安全管理的应用服务。2)ServerBootstrap是一个设置服务的帮助类。你甚至可以在这个服务中直接设置一个Channel通道。然而请注意,这是一个繁琐的过程,大多数情况下并不需要这样做。3)这里,我们将DiscardServerHandler处理器添加至默认的ChannelPipeline通道。任何时候当服务器接收到一个新的连接,一个新的ChannelPipeline管道对象将被创建,并且所有在这里添加的ChannelHandler对象将被添加至这个新的ChannelPipeline管道对象。这很像是一种浅拷贝操作(a shallow-copyoperation

14、);所有的Channel通道以及其对应的ChannelPipeline实例将分享相同的DiscardServerHandler实例。4)你也可以设置我们在这里指定的这个通道实现的配置参数。我们正在写的是一个TCP/IP服务,因此我们运行设定一些socket选项,例如tcpNoDelay和keepAlive。请注意我们在配置选项里添加的child.前缀。这意味着这个配置项仅适用于我们接收到的通道实例,而不是ServerSocketChannel实例。因此,你可以这样给一个ServerSocketChannel设定参数:bootstrap.setOption(reuseAddress, true)

15、;5)我们继续。剩下要做的是绑定这个服务使用的端口并且启动这个服务。这里,我们绑定本机所有网卡(NICs,network interfacecards)上的8080端口。当然,你现在也可以对应不同的绑定地址多次调用绑定操作。大功告成!现在你已经完成你的第一个基于Netty的服务端程序。1.3. 查看接收到的数据现在你已经完成了你的第一个服务端程序,我们需要测试它是否可以真正的工作。最简单的方法是使用telnet命令。例如,你可以在命令行中输入telnet localhost 8080 或其他类型参数。然而,我们可以认为服务器在正常工作吗?由于这是一个丢球协议服务,所以实际上我们无法真正的知道。

16、你最终将收不到任何回应。为了证明它在真正的工作,让我们修改代码打印其接收到的数据。我们已经知道当完成数据的接收后将产生MessageEvent消息事件,并且也会触发messageReceived处理方法。所以让我在DiscardServerHandler处理器的messageReceived方法内增加一些代码。Override public void messageReceived(ChannelHandlerContext ctx, MessageEvente) ChannelBuffer buf = (ChannelBuffer) e.getMessage(); while(buf.rea

17、dable() System.out.println(char) buf.readByte(); 代码说明1)基本上我们可以假定在socket的传输中消息类型总是ChannelBuffer。ChannelBuffer是Netty的一个基本数据结构,这个数据结构存储了一个字节序列。ChannelBuffer类似于NIO的ByteBuffer,但是前者却更加的灵活和易于使用。例如,Netty允许你创建一个由多个ChannelBuffer构建的复合ChannelBuffer类型,这样就可以减少不必要的内存拷贝次数。2)虽然ChannelBuffer有些类似于NIO的ByteBuffer,但强烈建议你

18、参考Netty的API手册。学会如何正确的使用ChannelBuffer是无障碍使用Netty的关键一步。如果你再次运行telnet命令,你将会看到你所接收到的数据。抛弃协议服务的所有源代码均存放在在分发版的ty.example.discard包下。1.4. 响应协议服务目前,我们虽然使用了数据,但最终却未作任何回应。然而一般情况下,一个服务都需要回应一个请求。让我们实现ECHO协议来学习如何完成一个客户请求的回应消息,ECHO协议规定要返回任何接收到的数据。与我们上一节实现的抛弃协议服务唯一不同的地方是,这里需要返回所有的接收数据而不是仅仅打印在控制台之上。因此我们再次修改messageRe

19、ceived方法就足够了。Override public void messageReceived(ChannelHandlerContext ctx, MessageEvente) Channel ch = e.getChannel(); ch.write(e.getMessage(); 代码说明1) 一个ChannelEvent通道事件对象自身存有一个和其关联的Channel对象引用。这个返回的Channel通道对象代表了这个接收MessageEvent消息事件的连接(connection)。因此,我们可以通过调用这个Channel通道对象的write方法向远程节点写入返回数据。现在如果你

20、再次运行telnet命令,你将会看到服务器返回的你所发送的任何数据。相应服务的所有源代码存放在分发版的ty.example.echo包下。1.5. 时间协议服务这一节需要实现的协议是TIME协议。这是一个与先前所介绍的不同的例子。这个例子里,服务端返回一个32位的整数消息,我们不接受请求中包含的任何数据并且当消息返回完毕后立即关闭连接。通过这个例子你将学会如何构建和发送消息,以及当完成处理后如何主动关闭连接。因为我们会忽略接收到的任何数据而只是返回消息,这应当在建立连接后就立即开始。因此这次我们不再使用messageReceived方法,取而代之的是使用channelConnected方法。下

21、面是具体的实现:package ty.example.time; ChannelPipelineCoverage(all) public class TimeServerHandler extends SimpleChannelHandler Override public void channelConnected(ChannelHandlerContext ctx,ChannelStateEvent e) Channel ch = e.getChannel(); ChannelBuffer time = ChannelBuffers.buffer(4); time.writeInt(Sys

22、tem.currentTimeMillis() / 1000); ChannelFuture f = ch.write(time); f.addListener(new ChannelFutureListener() public void operationComplete(ChannelFuture future) Channel ch = future.getChannel(); ch.close(); ); Override public void exceptionCaught(ChannelHandlerContext ctx,ExceptionEvent e) e.getCaus

23、e().printStackTrace(); e.getChannel().close(); 代码说明1)正如我们解释过的,channelConnected方法将在一个连接建立后立即触发。因此让我们在这个方法里完成一个代表当前时间(秒)的32位整数消息的构建工作。2) 为了发送一个消息,我们需要分配一个包含了这个消息的buffer缓冲。因为我们将要写入一个32位的整数,因此我们需要一个4字节的ChannelBuffer。ChannelBuffers是一个可以创建buffer缓冲的帮助类。除了这个buffer方法,ChannelBuffers还提供了很多和ChannelBuffer相关的实用方法

24、。更多信息请参考API手册。另外,一个很不错的方法是使用静态的导入方式:import static ty.buffer.ChannelBuffers.*;.ChannelBuffer dynamicBuf = dynamicBuffer(256);ChannelBuffer ordinaryBuf = buffer(1024);3) 像通常一样,我们需要自己构造消息。但是打住,flip在哪?过去我们在使用NIO发送消息时不是常常需要调用ByteBuffer.flip()方法吗?实际上ChannelBuffer之所以不需要这个方法是因为ChannelBuffer有两个指针;一个对应读操作,一个对

25、应写操作。当你向一个ChannelBuffer写入数据的时候写指针的索引值便会增加,但与此同时读指针的索引值不会有任何变化。读写指针的索引值分别代表了这个消息的开始、结束位置。与之相应的是,NIO的buffer缓冲没有为我们提供如此简洁的一种方法,除非你调用它的flip方法。因此,当你忘记调用flip方法而引起发送错误时,你便会陷入困境。这样的错误不会再Netty中发生,因为我们对应不同的操作类型有不同的指针。你会发现就像你已习惯的这样过程变得更加容易一种没有flippling的体验!另一点需要注意的是这个写方法返回了一个ChannelFuture对象。一个ChannelFuture对象代表了

26、一个尚未发生的I/O操作。这意味着,任何已请求的操作都可能是没有被立即执行的,因为在Netty内部所有的操作都是异步的。例如,下面的代码可能会关闭一 个连接,这个操作甚至会发生在消息发送之前:Channel ch = .;ch.write(message);ch.close();因此,你需要这个write方法返回的ChannelFuture对象,close方法需要等待写操作异步完成之后的ChannelFuture通知/监听触发。需要注意的是,关闭方法仍旧不是立即关闭一个连接,它同样也是返回了一个ChannelFuture对象。4)在写操作完成之后我们又如何得到通知?这个只需要简单的为这个返回的

27、ChannelFuture对象增加一个ChannelFutureListener即可。在这里我们创建了一个匿名ChannelFutureListener对象,在这个ChannelFutureListener对象内部我们处理了异步操作完成之后的关闭操作。另外,你也可以通过使用一个预定义的监听类来简化代码。f.addListener(ChannelFutureListener.CLOSE);1.6. 时间协议服务客户端不同于DISCARD和ECHO协议服务,我们需要一个时间协议服务的客户端,因为人们无法直接将一个32位的二进制数据转换一个日历时间。在这一节我们将学习如何确保服务器端工作正常,以及如

28、何使用Netty完成客户端的开发。使用Netty开发服务器端和客户端代码最大的不同是要求使用不同的Bootstrap及ChannelFactory。请参照以下的代码:package ty.example.time; import .InetSocketAddress; import java.util.concurrent.Executors; public class TimeClient public static void main(String args) throws Exception String host = args0; int port = Integer.parseInt

29、(args1); ChannelFactory factory = new NioClientSocketChannelFactory ( Executors.newCachedThreadPool(), Executors.newCachedThreadPool(); ClientBootstrap bootstrap = new ClientBootstrap (factory); TimeClientHandler handler = new TimeClientHandler(); bootstrap.getPipeline().addLast(handler, handler); b

30、ootstrap.setOption(tcpNoDelay , true); bootstrap.setOption(keepAlive, true); bootstrap.connect (new InetSocketAddress(host, port); 代码说明1)使用NioClientSocketChannelFactory而不是NioServerSocketChannelFactory来创建客户端的Channel通道对象。2) 客户端的ClientBootstrap对应ServerBootstrap。3) 请注意,这里不存在使用child.前缀的配置项,客户端的SocketChannel实例不存在父级Channel对象。4) 我们应当调用connect连接方法,而不是之前的bind绑定方法。正如你所看到的,这与服务端的启动过程是完全不一样的。ChannelHandler又该如何实现呢?它应当负责接收一个32位的整数,将其转换为可读的格式后,打印输出时间,并关闭这个连接。 package org.j

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1