第2章 你的第一款Netty应用程序

本章主要内容

  • 设置开发环境
  • 编写Echo服务器和客户端
  • 构建并测试应用程序

在本章中,我们将展示如何构建一个基于Netty的客户端和服务器。应用程序很简单:客户端将消息发送给服务器,而服务器再将消息回送给客户端。但是这个练习很重要,原因有两个。

首先,它会提供一个测试台,用于设置和验证你的开发工具和环境,如果你打算通过对本书的示例代码的练习来为自己将来的开发工作做准备,那么它将是必不可少的。

其次,你将获得关于Netty的一个关键方面的实践经验,即在前一章中提到过的:通过ChannelHandler来构建应用程序的逻辑。这能让你对在第3章中开始的对Netty API的深入学习做好准备。

2.1 设置开发环境

要编译和运行本书的示例,只需要JDK和Apache Maven这两样工具,它们都是可以免费下载的。

我们将假设,你想要捣鼓示例代码,并且想很快就开始编写自己的代码。虽然你可以使用纯文本编辑器,但是我们仍然强烈地建议你使用用于Java的集成开发环境(IDE)。

2.1.1 获取并安装Java开发工具包

你的操作系统可能已经安装了JDK。为了找到答案,可以在命令行输入:

javac -version

如果得到的是javac 1.7……或者1.8……,则说明已经设置好了并且可以略过此步[1]

否则,请从http://java.com/en/download/manual.jsp处获取JDK第8版。请留心,需要下载的是JDK,而不是Java运行时环境(JRE),其只可以运行Java应用程序,但是不能够编译它们。该网站为每个平台都提供了可执行的安装程序。如果需要安装说明,可以在同一个网站上找到相关的信息。

建议执行以下操作:

  • 将环境变量JAVA_HOME设置为你的JDK安装位置(在Windows上,默认值将类似于C:\Program Files\Java\jdk1.8.0_121);
  • %JAVA_HOME%\bin(在Linux上为${JAVA_HOME}/bin)添加到你的执行路径。

2.1.2 下载并安装IDE

下面是使用最广泛的Java IDE,都可以免费获取:

  • Eclipse—— www.eclipse.org;
  • NetBeans—— www.netbeans.org;
  • Intellij IDEA Community Edition—— www.jetbrains.com。

所有这3种对我们将使用的构建工具Apache Maven都拥有完整的支持。NetBeans和Intellij IDEA都通过可执行的安装程序进行分发。Eclipse通常使用Zip归档文件进行分发,当然也有一些自定义的版本包含了自安装程序。

2.1.3 下载和安装Apache Maven

即使你已经熟悉Maven了,我们仍然建议你至少大致浏览一下这一节。

Maven是一款广泛使用的由Apache软件基金会(ASF)开发的构建管理工具。Netty项目以及本书的示例都使用了它。构建和运行这些示例并不需要你成为一个Maven专家,但是如果你想要对其进行扩展,我们推荐你阅读附录中的Maven简介。

你需要安装Maven吗

Eclipse和NetBeans[2]自带了一个内置的Maven安装包,对于我们的目的来说开箱即可工作得良好。如果你将要在一个拥有它自己的Maven存储库的环境中工作,那么你的配置管理员可能就有一个预先配置好的能配合它使用的Maven安装包。

在本书中文版出版时,Maven 的最新版本是3.3.9。你可以从http://maven.apache.org/ download.cgi下载适用于你的操作系统的tar.gz或者zip归档文件[3]。安装很简单:将归档文件的所有内容解压到你所选择的任意的文件夹(我们将其称为<安装目录>)。这将创建目录<安装目录>\apache-maven-3.3.9。

和设置Java环境一样:

  • 将环境变量M2_HOME设置为指向<安装目录>\apache-maven-3.3.9;
  • %M2_HOME%\bin(或者在Linux上为${M2_HOME}/bin)添加到你的执行路径。

这将使得你可以通过在命令行执行mvn.bat(或者mvn)来运行Maven。

2.1.4 配置工具集

如果你已经按照推荐设置好了环境变量JAVA_HOMEM2_HOME,那么你可能会发现,当你启动自己的IDE时,它已经发现了你的Java和Maven的安装位置。如果你需要进行手动配置,我们所列举的所有的IDE版本在Preferences或者Settings下都有设置这些变量的菜单项。相关的细节请查阅文档。

这就完成了开发环境的配置。在接下来的各节中,我们将介绍你要构建的第一个Netty应用程序的详细信息,同时我们将更加深入地了解该框架的API。之后,你就能使用刚刚设置好的工具来构建和运行Echo服务器和客户端了。

2.2 Netty客户端/服务器概览

图2-1从高层次上展示了一个你将要编写的Echo客户端和服务器应用程序。虽然你的主要关注点可能是编写基于Web的用于被浏览器访问的应用程序,但是通过同时实现客户端和服务器,你一定能更加全面地理解Netty的API。

图2-1 Echo客户端和服务器

虽然我们已经谈及到了客户端,但是该图展示的是多个客户端同时连接到一台服务器。所能够支持的客户端数量,在理论上,仅受限于系统的可用资源(以及所使用的JDK版本可能会施加的限制)。

Echo客户端和服务器之间的交互是非常简单的;在客户端建立一个连接之后,它会向服务器发送一个或多个消息,反过来,服务器又会将每个消息回送给客户端。虽然它本身看起来好像用处不大,但它充分地体现了客户端/服务器系统中典型的请求-响应交互模式。

我们将从考察服务器端代码开始这个项目。

2.3 编写Echo服务器

所有的Netty服务器都需要以下两部分。

  • 至少一个ChannelHandler——该组件实现了服务器对从客户端接收的数据的处理,即它的业务逻辑。
  • 引导——这是配置服务器的启动代码。至少,它会将服务器绑定到它要监听连接请求的端口上。

在本小节的剩下部分,我们将描述Echo服务器的业务逻辑以及引导代码。

2.3.1 ChannelHandler和业务逻辑

在第1章中,我们介绍了Future和回调,并且阐述了它们在事件驱动设计中的应用。我们还讨论了ChannelHandler,它是一个接口族的父接口,它的实现负责接收并响应事件通知。在Netty应用程序中,所有的数据处理逻辑都包含在这些核心抽象的实现中。

因为你的Echo服务器会响应传入的消息,所以它需要实现ChannelInboundHandler接口,用来定义响应入站事件的方法。这个简单的应用程序只需要用到少量的这些方法,所以继承Channel-InboundHandlerAdapter类也就足够了,它提供了ChannelInboundHandler的默认实现。

我们感兴趣的方法是:

  • channelRead()——对于每个传入的消息都要调用;
  • channelReadComplete()——通知ChannelInboundHandler最后一次对channel-Read()的调用是当前批量读取中的最后一条消息;
  • exceptionCaught()——在读取操作期间,有异常抛出时会调用。

该Echo服务器的ChannelHandler实现是EchoServerHandler,如代码清单2-1所示。

代码清单2-1 EchoServerHandler

@Sharable  ⇽--- 标示一个Channel- Handler可以被多个Channel安全地共享
public class EchoServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {ByteBuf in = (ByteBuf) msg;System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));     ⇽---  将消息记录到控制台       ctx.write(in);   ⇽--- 将接收到的消息写给发送者,而不冲刷出站消息}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) {ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);   ⇽--- 将未决消息冲刷到远程节点,并且关闭该Channel}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) {cause.printStackTrace();     ⇽---  打印异常栈跟踪ctx.close();  ⇽--- 关闭该Channel}
}

ChannelInboundHandlerAdapter有一个直观的API,并且它的每个方法都可以被重写以挂钩到事件生命周期的恰当点上。因为需要处理所有接收到的数据,所以你重写了channelRead()方法。在这个服务器应用程序中,你将数据简单地回送给了远程节点。

重写exceptionCaught()方法允许你对Throwable的任何子类型做出反应,在这里你记录了异常并关闭了连接。虽然一个更加完善的应用程序也许会尝试从异常中恢复,但在这个场景下,只是通过简单地关闭连接来通知远程节点发生了错误。

如果不捕获异常,会发生什么呢

每个Channel都拥有一个与之相关联的ChannelPipeline,其持有一个ChannelHandler的实例链。在默认的情况下,ChannelHandler会把对它的方法的调用转发给链中的下一个Channel-Handler。因此,如果exceptionCaught()方法没有被该链中的某处实现,那么所接收的异常将会被传递到ChannelPipeline的尾端并被记录。为此,你的应用程序应该提供至少有一个实现了exceptionCaught()方法的ChannelHandler。(6.4节详细地讨论了异常处理)。

除了ChannelInboundHandlerAdapter之外,还有很多需要学习的ChannelHandler的子类型和实现,我们将在第6章和第7章中对它们进行详细的阐述。目前,请记住下面这些关键点:

  • 针对不同类型的事件来调用ChannelHandler
  • 应用程序通过实现或者扩展ChannelHandler来挂钩到事件的生命周期,并且提供自定义的应用程序逻辑;
  • 在架构上,ChannelHandler有助于保持业务逻辑与网络处理代码的分离。这简化了开发过程,因为代码必须不断地演化以响应不断变化的需求。
  • 转载自 并发编程网 - ifeve.com

《Netty 实战》Netty In Action中文版 第2章——你的第一款Netty应用程序(一)相关推荐

  1. 阿里P8架构师首推Netty实战,实战篇+面试篇,将知识点一网打尽

    又逢"金九银十",年轻的毕业生们满怀希望与忐忑,去寻找.竞争一个工作机会.已经在职的开发同学,也想通过社会招聘或者内推的时机争取到更好的待遇.更大的平台. 然而,面试人群众多,技术 ...

  2. 《Netty IN ACTION》中文版《Netty实战》翻译手记——不负好时光

    不负好时光--<Netty in Action>中文版<Netty实战>翻译手记 引子 "书中自有黄金屋,书中自有颜如玉",这句话从小我老爸就给我讲,当然那 ...

  3. 不负好时光——《Netty in Action》中文版《Netty实战》翻译手记

    引子 "书中自有黄金屋,书中自有颜如玉",这句话从小我老爸就给我讲,当然那个时候真的以为书中真的会有黄金做的屋子和很多玉件.后来慢慢长大了,也渐渐懂得了这句话背后的真正含义.当然, ...

  4. Netty In Action中文版

    第一章:Netty介绍 本章介绍 Netty介绍 为什么要使用non-blocking IO(NIO) 阻塞IO(blocking IO)和非阻塞IO(non-blocking IO)对比 Java ...

  5. Netty In Action中文版 - 第十二章:SPDY

    Netty In Action中文版 - 第十二章:SPDY 本章我将不会直接翻译Netty In Action书中的原文,感觉原书中本章讲的很多废话,我翻译起来也吃力.所以,本章内容我会根据其他资料 ...

  6. 手淘、微博一直钟情的_Netty框架是个什么鬼?_参与互动可获《Netty实战》新书

    原文链接 手淘.微博一直钟情的 Netty框架是个什么鬼? 发布时间:2017-05-15 18:23:06861人关注47人参与 众所周知,构建高性能的现代互联网架构,我们一定离不开分布式系统,这些 ...

  7. Netty实战 IM即时通讯系统(七)数据传输载体ByteBuf介绍

    ## Netty实战 IM即时通讯系统(七)数据传输载体ByteBuf介绍 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向 ...

  8. Netty实战 IM即时通讯系统(十二)构建客户端与服务端pipeline

    Netty实战 IM即时通讯系统(十二)构建客户端与服务端pipeline 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向 ...

  9. Netty实战 IM即时通讯系统(十一)pipeline与channelHandler

    Netty实战 IM即时通讯系统(十一)pipeline与channelHandler 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端 ...

最新文章

  1. Java学习总结:13
  2. Spring MVC常用注解说明
  3. Eclipse 安装配置指南
  4. 160个Crackme036
  5. java %1$s_%1$s %1$d Android string (java Android 格式化字符串)
  6. Vue.js 定义组件模板的七种方式
  7. ASP.NET简易教程3——SQL存储过程
  8. 在linux中怎么装python3环境,在Linux环境下安装Python3
  9. JVM-常用内存调优参数总结
  10. 归档日志路径三个参数DB_RECOVERY_FILE_DEST和LOG_ARCHIVE_DEST和LOG_ARCHIVE_DEST_n
  11. 图片,视频,文件等非结构化数据存储建议
  12. 练习3-2,编写一个函数escape(s,t),将字符串t复制到字符串s中,并在复制过程中将换行符、制表符等不可见字符转换为\n、\t等相应的可见的转义字符序列。要求使用switch语句。
  13. scscanner:一款功能强大的大规模状态码扫描工具
  14. Oracle启用、禁用触发器
  15. 丙丙-2个月面试20家大厂的知识点总结和建议(答案)
  16. 使用Python 训练OpenCV Cascade分类器 - 1
  17. 小学数学与计算机整合课优质教案,小学数学优质课教案《长方形的面积》(通用5篇)...
  18. z(xi)i取1到n编入matlab,matlab fisher z转换
  19. 工程伦理--15.5 克隆技术和干细胞研究的伦理问题(上)
  20. 8音度dsp调音教程_8音度手把手教你调音玩转dsp教学内容

热门文章

  1. SQL注入攻击再度肆虐殃及大量网站
  2. php 算法 数字比较,数据两两比较的高效算法?
  3. 通过加载 QSS 文件的方式美化 QT 界面
  4. JavaSE(七)——Scanner类、String类
  5. 格式说明_现代诗歌的写作格式是什么,能否举例说明?
  6. 计算机视觉--Python实现人体姿态估计
  7. 北斗导航 | 北斗RDSS短报文通信及定位原理(RD双星定位、通信与授时、附代码)
  8. Matlab | Matlab从入门到放弃(4)——样本均值
  9. java8 b计算时间差_java8-计算时间差的方法
  10. python3精要(31)-生成器函数yield