Netty官网文档:4.X版本的用户引导教程翻译及理解(未完成)
User guide for 4.x
Preface
前言
The Problem
Nowadays we use general purpose applications or libraries to communicate with each other. For example, we often use an HTTP client
library to retrieve information from a web server and to invoke a remote procedure call via web services. However, a general purpose
protocol or its implementation sometimes does not scale very well. It is like how we don't use a general purpose HTTP server to
exchange huge files, e-mail messages, and near-realtime messages such as financial information and multiplayer game data. What's
required is a highly optimized protocol implementation that is dedicated to a special purpose. For example, you might want to implement
an HTTP server that is optimized for AJAX-based chat application, media streaming, or large file transfer. You could even want to
design and implement a whole new protocol that is precisely tailored to your need. Another inevitable case is when you have to deal
with a legacy proprietary protocol to ensure the interoperability with an old system. What matters in this case is how quickly we can
implement that protocol while not sacrificing the stability and performance of the resulting application.
现在我们使用通用的应用程序或库来相互通信。例如,我们经常使用HTTP客户端库从web服务器检索信息,并通过web服务器调用远程程序。
然而,一个通用协议或其实现有的时候不能很好的扩展。这就像我们不适用HTTP服务器来交换大文件、电子邮件、和近乎时时的消息,如财务信息
和多人游戏数据。我们需要的是一个专门用于特殊目的的高度优化的协议实现。例如,您可能希望实现一个针对基于AJAX的聊天应用程序、媒体流、
或大型文件传输的HTTP服务器,您甚至可以设计并实现一个完全根据您自己需求的新协议。另一个不可避免的情况是当您必须处理遗留的专有协议
以确保与旧系统的互操作性。在这种情况下,重要的是我们可以多快的实现该协议,同时又不会牺牲结果应用程序的稳定性和性能。
The Solution
The Netty project is an effort to provide an asynchronous event-driven network application framework and tooling for the rapid
development of maintainable high-performance and high-scalability protocol servers and clients.
Netty项目旨在提供一个异步的事件驱动网络应用程序框架和工具,用于快速开发可维护性的高性能和高扩展性协议的服务器和客户端。
In other words, Netty is an NIO client server framework that enables quick and easy development of network applications such as
protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server development.
换句话说,Netty是一个NIO客户端-服务器 框架,它支持快速而容易的开发网络应用程序,如协议服务器和客户端。它极大的简化了网络程序如TCP
和 UDP 套接字服务器的开发。
'Quick and easy' does not mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been
designed carefully with the experiences learned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various
binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance,
stability, and flexibility without a compromise.
快速简单 并不意味着结果应用程序必须面临可维护性和性能的问题,Netty经过了精心的设计,从许多协议(如FTP, SMTP, HTTP以及各种二进制和基于文本的遗留协议)
的实现中汲取经验。因此,Netty 已经成功的找到了一种不妥协的方式来实现开发、性能、稳定性和灵活性。
Some users might already have found other network application frameworks that claim to have the same advantage, and you might
want to ask what makes Netty so different from them. The answer is the philosophy it is build on. Netty is designed to give you the most
comfortable experience both in terms of the API and the implementation from day one. It is not something tangible but you will realize
that this philosophy will make your life much easier as you read this guide and play with Netty.
一些用户可能已经找到了其他声称具有相同优势的网络应用程序框架。您可能想问是什么使得Netty与他们如此不同。答案是它所建立的哲学。
Netty的设计目的是从第一天开始就为您提供API 和 实现方面的最舒适的体验。 这并不是什么有形的东西, 但你会意识到, 这种哲学让你的生活
如此轻松 就如同你读Netty 文档和使用Netty一样。
Getting Started
This chapter tours around the core constructs of Netty with simple examples to let you get started quickly. You will be able to write a
client and a server on top of Netty right away when you are at the end of this chapter.
这章用一些简单的示例介绍了Netty的核心结构让你快速入门。在本章结束的时候, 您将能够立即在Netty上编写客户端和服务器程序
if you prefer a top-down approach in learning something, you might want to start from Chapter 2, Architectural Overview and get back
here.
如果您比较喜欢自上而下的学习方法。您可能希望从第二章 体系结构概述 开始 然后 再回到这里。
The minimum requirements to run the examples in this chapter are only two : the latest version of Netty and JDK 1.6 or above. The
latest version of Netty is avalible in the project download page. To download the right version of JDK, please refer to your preferred
JDK vendor's web site.
运行本章例子的最低需求只有两个:最新版本的Netty 以及JDK1.6或以上版本。Netty的最新版本可以在项目下载页面下载到。要下载正确
版本的JDK, 请参照您首选的JDK供应商网站。
As you read, you might have more questions about classes introduced in this chapter, Please refer to API reference whenver
you want to know more about them. All class names in this document are linked to the online API reference for your convenience.
Also, please don't hesitate to contact the Netty project community and let us know if there's any incorrect information、 errors in
grammar or typos, and if you have any good ideas to help improve the documentation.
阅读时, 您可能会对本章中介绍的类有许多疑问。如果您想了解更多信息,请你参考API。为方便起见,本文档中的所有类名都链接到联机
的API引用。另外,请不要犹豫,联系Netty项目社区,让我们知道是否有任何不正确的信息,语法错误或者打字错误,或者你是否有好主意
帮助改进文档。
Writing a Discard Server
The most simplistic protocol in the world is not 'Hello, World!' but DISCARD, It's a protocol that discards any received data without any response.
To implement the DISCARD protocol, the only thing you need to do is to ignore all received data. Let us start straight from the handler implementation,
which handles I/O events generated by Netty.
这个世界最简单的协议不是Hello,World! 而是DISCARD, 它是一个没有回应就抛弃任何接收到的数据的协议,
要实现DISCARD协议,您只需要忽略所有接收到的数据。让我们直接从处理程序实现开始,它处理Netty生成的I/O事件。
package io.netty.example.discard; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** * Handles a server-side channel. */ public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1) @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2) // Discard the received data silently. ((ByteBuf) msg).release(); // (3) } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4) // Close the connection when an exception is raised. cause.printStackTrace(); ctx.close(); } }
1. DiscardServerHandler extends ChannelInboundHandlerAdaper, which is an implementation of ChannelInboundHandler.ChannelInboundHandler provides various event handler methods that you can override. For now, it is just enough to extends ChannelInboundHandlerAdaper rather than to implement the handler interface by yourself.
DiscardServerHandler 继承自 ChannelInboundHandlerAdaper,它是一个ChannelInboundHandler的实现。ChannelInboundHandler提供了各种可重写的事件处理程序方法。目前,只需扩展channelinboundhandleradopter,而不必自己实现handler接口。
2.We override the channelRead() event handler method here. This method is called with the received message, whenever new data is received from a client. In this example, the type of the received message is ByteBuf.
我们在这里重写了channelRead时间处理方法,每当从客户端接收到新数据时,将使用接收到的消息调用此方法。 在本例中接收到的消息是ByteBuf。(有可能接收到的消息是其他类型 如BinaryWebSocketFrame)
3. To implement the DISCARD protocol, the handler has to ignore the received message. ByteBuf is a reference-counted object which has to be released explicitly via the release() method. Please keep in mind that it is the handler's responsibility to release any reference-counted object passed to the handler. Usually, channelRead() handler method is implemented like the following:
要实现丢弃协议,处理程序必须忽略接收到的消息。 ByteBuf是一个引用计数对象, 必须通过release()方法显式释放。 请记住, 处理程序有责任释放传递给程序的任何引用计数对象。 通常,channelRead()处理方法实现如下:
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) { try { // Do something with msg } finally { ReferenceCountUtil.release(msg); } }
4. The exceptionCaught() event method is called with a Throwable when an exception was raised by Netty due to an I/O error or by a handler implementation due to the exception thrown while processing events. In most cases, the caught exception should be logged and its associated channel should be closed here, although the implementation of this method can be different depending on what you want to do to deal with an exceptional situation. For example, you might want to send a response message with an error code before closing the connection.
当Netty因I/O错误引发异常, 或处理实现因处理事件引发异常时,使用一个Throwable调用exceptionCought事件处理方法。 在大多数情况下, 应该记录捕获的异常, 并关闭其关联的信道, 尽管此方法的实现会有所不同,具体取决于您希望如何处理异常情况。 例如,您可能希望在关闭连接前发送带有错误代码的响应消息。
So far so good. We have implemented the first half of the DISCARD server. What's left now is to write the main() method which starts the server with the DiscardServerHandler.
到现在为止,一直都还不错。我们已经实现了DISCARD服务器的前半部分。现在剩下的是编写main()方法,该方法使用DiscardServerHandler启动服务器。
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; /** * Discards any incoming data. */ public class DiscardServer { private int port; public DiscardServer(int port) { this.port = port; } public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new ChannelInitializer<SocketChannel>() { // (4) @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new DiscardServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) // Bind and start to accept incoming connections. ChannelFuture f = b.bind(port).sync(); // (7) // 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. f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 8080; if (args.length > 0) { port = Integer.parseInt(args[0]); } new DiscardServer(port).run(); } }
1、 NioEventLoopGroup is a multithreaded event loop that handles I/O operation.Netty provides various EventLoopGroup implementations for different kind of transports. We are implementing a server-side application in this example, and therefore two NioEventLoopGroup will be used. The first one, often called 'boss', accepts an incoming connections. The second one, often called 'worker', handlers the traffic of the accepted connection once the boss
accepts the connetion and register the accepted connetion to the worker.How many Threads are used and how they are mapped to the created Channels depends on the EventLoopGroup implementation and may be even configurable via a constructor.
NioEventLoopGroup 是一个处理I/O操作的多线程事件循环,Netty 为不同的传输类型提供了不同的EventLoopGroup实现, 这个例子我们正在实现一个服务器端的应用程序, 因此使用两个NioEventLoopGroup, 第一个, 通常称之为boss, 接收一个新到来的连接, 第二个,通常称之为worker, 用来处理boss接收了连接且注册连接到worker后的通信, 使用多少个线程以及他们是怎么被映射到创建出来的通道的, 取决于EventLoopGroup的实现,甚至可以通过构造函数配置。
2、 ServerBootstrap is a helper class that sets up a server.You can set up the server using a Channel Directly, However,please note that this is a tedious process, and you do not need to do that in most cases.
ServerBootstrap 是一个设置服务器的辅助类。 你可以直接使用通道设置一个服务器,但是请注意, 这是一个乏味的过程, 很多情况下你没必要这么做。
3、 Here, we specify to use the NioServerSocketChannel class which is used to instantiate a new Channel to accept incoming connections.
这里, 我们指定使用NioServerSocketChannel 类来实例化接收到的连接。
4、 The handler specified here will always be evaluated by a newly accepted Channel.The ChannelInitializer is a special handler that is purpose to help a user configure a new Channel. It is most likely that you want to configure the ChannelPipeline of the new Channel by adding some handlers such as DiscardServerHandler to implement your network application. As the application gets complicated, it is likely that you will add more handlers to the pipeline and extract this anonymous class into a top-level class eventually.
此处指定的处理(childHandler)总是被一个新连接的通道计算, ChannelInitializer是为了帮助用户配置一个新的通道指定的方法。 您很可能希望通过添加一些处理器诸如(DiscardServerHandler)来配置新通道的ChannePipeline, 以实现你的网络应用程序, 当应用程序变得复杂时, 你很可能希望向通道中添加更多的处理器并最终将这个匿名类提取到顶级类中。(初始化器用来每次接收到新连接的时候的时候调用initChannel()方法来初始化信道,初始化的时候可以往信道上的pipeline即ch.pipeline().addLast() 添加各种处理器(诸如消息从客户端传过来后的解码器,解码后的消息如何处理的处理器、以及构造了新的回传消息的编码器 等等)进去)
5、 You can also set the parameters which are specific to the Channel implementation. We are writing a TCP/IP server. so we are allow to set the socket options such as tcpNoDelay and keepAlive. Please refer to the apidocs of ChannelOption and the specific ChannelConfig implementations to get an overview about the supported ChannelOptions.
你还可以设置特定于通道实现的参数列表。 我们正在写一个TCP/IP的服务端。 所以我们允许设置诸如tcpNoDelay 和 keepAlive 的套接字选项, 请参考ChannelOption的api文档和特定的ChannelConfig 实现, 以了解已支持的ChannelOption概述。
6、 Did you notice option() and childOption()? option() is for the NioServerSocketChannel that accepts incoming connections. childOption() is for the Channels accepted by the parent ServerChannel, which is NioServerSocketChannel in this case.
你是否已经注意到了 option() 和 childOption()? option()是用于接收新连接的NioServerSocketChannel, 而childOption()则是用于被父服务器通道接收到的通道, 在本例中则是NioServerSocketChannel。(option 和 childOption 都是可配置的参数) (有点类似插座和插头 一个服务端插座 可以连接N个客户端插头)
7、 We are ready to go now. What's left is to bind to the port and to start the server. Here, we bind to the port 8080 of all NICs(network interface cards) in the machine. You can now call the bind() method as many times as you want(with different bind addresses.) (这里使用ServerBootstrap的实例对象b来绑定端口 b.bind(8080).sync() 这里的sync 返回一个ChannelFuture 的实例f 【f.channel.closeFuture().sync】是固定写法 )
我们现在可以准备出发了, 剩下的是绑定到端口并启动服务器, 此处我们绑定到所有端口中的8080端口。 现在你可以根据需要多次调用bind()方法(使用不同的绑定地址)
Congratulations! You have just finished your first server on top of Netty.
恭喜!你已经完成了基于Netty的第一个服务器。
浙公网安备 33010602011771号