不像 DISCARD 和 ECHO 的服务端,对于 TIME 协议我们需要一个客户端,因为人们不能把一个32位的二进制数据翻译成一个日期或者日历。在这一部分,我们将会讨论如何确保服务端是正常工作的,并且学习怎样用Netty 编写一个客户端。在 Netty 中,编写服务端和客户端最大的并且唯一不同的使用了不同的BootStrap 和 Channel的实现。
在这个部分被实现的协议是 TIME 协议。和之前的例子不同的是在不接受任何请求时他会发送一个含32位的整数的消息,并且一旦消息发送就会立即关闭连接。在这个例子中,你会学习到如何构建和发送一个消息,然后在完成时关闭连接。
到目前为止,我们虽然接收到了数据,但没有做任何的响应。然而一个服务端通常会对一个请求作出响应。让我们学习怎样在 ECHO 协议的实现下编写一个响应消息给客户端,这个协议针对任何接收的数据都会返回一个响应。和 discard server 唯一不同的是把在此之前我们实现的 channelRead() 方法,返回所有的数据替代打印接收数据到控制台上的逻辑。
现在我们已经编写出我们第一个服务端,我们需要测试一下他是否真的可以运行。最简单的测试方法是用 telnet 命令。例如,你可以在命令行上输入telnet localhost 8080或者其他类型参数。然而我们能说这个服务端是正常运行了吗?事实上我们也不知道,因为他是一个 discard 服务,你根本不可能得到任何的响应。
世上最简单的协议不是'Hello, World!' 而是 DISCARD(丢弃)。这个协议将会丢掉任何收到的数据,而不响应。为了实现 DISCARD 协议,你只需忽略所有收到的数据。让我们从 handler (处理器)的实现开始,handler 是由 Netty 生成用来处理 I/O 事件的。 import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.
在运行本章示例之前,需要准备:最新版的 Netty 以及 JDK 1.6 或以上版本。最新版的 Netty 在这下载。自行下载 JDK。阅读本章节过程中,你可能会对相关类有疑惑,关于这些类的详细的信息请请参考 API 说明文档。为了方便,所有文档中涉及到的类名字都会被关联到一个在线的 API 说明。
本章围绕 Netty 的核心架构,通过简单的示例带你快速入门。当你读完本章节,你马上就可以用 Netty 写出一个客户端和服务器。如果你在学习的时候喜欢“top-down(自顶向下)”,那你可能需要要从第二章《Architectural Overview (架构总览)》开始,然后再回到这里。
Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能、高可靠性协议的服务器和客户端。换句话说,Netty 是一个 NIO 客户端服务器框架,使用它可以快速简单地开发网络应用程序,比如服务器和客户端的协议。Netty 大大简化了网络程序的开发过程比如 TCP 和 UDP 的 socket 服务的开发。
今天,我们使用通用的应用程序或者类库来实现互相通讯,比如,我们经常使用一个 HTTP 客户端库来从 web 服务器上获取信息,或者通过 web 服务来执行一个远程的调用。然而,有时候一个通用的协议或他的实现并没有很好的满足需求。比如我们无法使用一个通用的 HTTP 服务器来处理大文件、电子邮件以及近实时消息,比如金融信息和多人游戏数据。
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序dsf。《Netty 4.x 用户指南》中文翻译。至今为止,Netty 的最新版本为 4.0.27.Final(2015-04-01)。文本用到的所有例子源码可以在https://github.com/waylau/netty-4-user-guide-demos 获取到。
简介time.h 头文件定义了四个变量类型、两个宏和各种操作日期和时间的函数。库变量下面是头文件 time.h 中定义的变量类型: 序号变量 & 描述 1size_t 是无符号整数类型,它是 sizeof 关键字的结果。 2clock_t 这是一个适合存储处理器时间的类型。 3time_t is 这是一个适合存储日历时间类型。 4struct tm 这是一个用来保存时间和日期的结构。
简介string .h 头文件定义了一个变量类型、一个宏和各种操作字符数组的函数。库变量下面是头文件 string.h 中定义的变量类型: 序号变量 & 描述 1size_t 这是无符号整数类型,它是 sizeof 关键字的结果。 库宏下面是头文件 string.h 中定义的宏: 序号宏 & 描述 1NULL这个宏是一个空指针常量的值。 库函数下面是头文件 string.
简介stdlib .h 头文件定义了四个变量类型、一些宏和各种通用工具函数。库变量下面是头文件 stdlib.h 中定义的变量类型: 序号变量 & 描述 1size_t 这是无符号整数类型,它是 sizeof 关键字的结果。 2wchar_t 这是一个宽字符常量大小的整数类型。 3div_t 这是 div 函数返回的结构。 4ldiv_t 这是 ldiv 函数返回的结构。 库宏下面是头文件 stdlib.
简介stdio .h 头文件定义了三个变量类型、一些宏和各种函数来执行输入和输出。库变量下面是头文件 stdio.h 中定义的变量类型: 序号变量 & 描述 1size_t 这是无符号整数类型,它是 sizeof 关键字的结果。 2FILE 这是一个适合存储文件流信息的对象类型。 3fpos_t 这是一个适合存储文件中任何位置的对象类型。 库宏下面是头文件 stdio.
简介stddef .h 头文件定义了各种变量类型和宏。这些定义中的大部分也出现在其它头文件中。库变量下面是头文件 stddef.h 中定义的变量类型: 序号变量 & 描述 1ptrdiff_t这是有符号整数类型,它是两个指针相减的结果。 2size_t 这是无符号整数类型,它是 sizeof 关键字的结果。 3wchar_t 这是一个宽字符常量大小的整数类型。 库宏下面是头文件 stddef.
简介stdarg.h 头文件定义了一个变量类型 va_list 和三个宏,这三个宏可用于在参数个数未知(即参数个数可变)时获取函数中的参数。可变参数的函数通在参数列表的末尾是使用省略号(,...)定义的。库变量下面是头文件 stdarg.h 中定义的变量类型: 序号变量 & 描述 1va_list 这是一个适用于 va_start()、va_arg() 和 va_end() 这三个宏存储信息的类型。
简介signal.h 头文件定义了一个变量类型 sig_atomic_t、两个函数调用和一些宏来处理程序执行期间报告的不同信号。库变量下面是头文件 signal.h 中定义的变量类型: 序号变量 & 描述 1sig_atomic_t 这是 int 类型,在信号处理程序中作为变量使用。它是一个对象的整数类型,该对象可以作为一个原子实体访问,即使存在异步信号时,该对象可以作为一个原子实体访问。
简介setjmp.h 头文件定义了宏 setjmp()、函数 longjmp() 和变量类型 jmp_buf,该变量类型会绕过正常的函数调用和返回规则。库变量下面列出了头文件 setjmp.h 中定义的变量: 序号变量 & 描述 1jmp_buf 这是一个用于存储宏 setjmp() 和函数 longjmp() 相关信息的数组类型。 库宏下面是这个库中定义的唯一的一个宏: 序号宏 &
简介math.h 头文件定义了各种数学函数和一个宏。在这个库中所有可用的功能都带有一个 double 类型的参数,且都返回 double 类型的结果。库宏下面是这个库中定义的唯一的一个宏: 序号宏 & 描述 1 HUGE_VAL当函数的结果不可以表示为浮点数时。
简介locale.h 头文件定义了特定地域的设置,比如日期格式和货币符号。接下来我们将介绍一些宏,以及一个重要的结构 struct lconv 和两个重要的函数。库宏下面列出了头文件 locale.h 中定义的宏,这些宏将在下列的两个函数中使用: 序号宏 & 描述 1 LC_ALL设置下面的所有选项。 2 LC_COLLATE影响 strcoll 和 strxfrm 函数。 3 LC_CTYPE影响所有字符函数。
关注时代Java