Netty 5.X 官方指南翻译版2

继续翻译:http://netty.io/wiki/user-guide-for-5.x.html

写一个Discard服务器

最简单的协议不是hello,而是DISCARD

也就是说,忽略所有收到的数据,不返回任何响应。

为了完成这个协议,你仅仅需要做的是忽略所有收到的数据,让我们开始从handler实现开始,这个处理IO事件(来源于Netty).

package io.netty.example.discard;

 

import io.netty.buffer.ByteBuf;

 

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.ChannelHandlerAdapter;

 

/**

 * Handles a server-side channel.

 */

public class DiscardServerHandler extends ChannelHandlerAdapter { // (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();

    }

}

DiscardServerHandler extends ChannelHandlerAdapter是对ChannelHandler的一个实现ChannelHandler 提供了各种各样的事件方法可覆盖.

目前,继承 ChannelHandlerAdapter足够了 而不是自己实现接口里的方法。

 

我们重写了channelRead() 事件方法,这个方法被接收到的消息调用,当从客户端里接收到新数据时。在这个例子当中,接收到的信息是 ByteBuf.

为了实现DISCARD协议,方法必须忽略收到的消息,ByteBuf 是一个计数器方式引用的对象,只有显式的通过release()方法才可以释放这个对象。请注意:这个handler有责任来释放任何传给自己的计数器引用的对象。

通常, channelRead() 方法用以下形式实现

 

@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {    try {        // Do something with msg    } finally {        ReferenceCountUtil.release(msg);    }}

 

 

The exceptionCaught() 事件方法:

当处理事件时,IO错误或者handler实现里有异常抛出。

大多数情况下,异常应该记录下来,并且相关的channel应该被关闭,尽管这个方法的实现可以不同,这依赖于你想怎么处理。

比如,你也许想发送一个响应消息伴随错误码在关闭连接之前。

我们已经实现了一半,剩下的是写main()方法来启动这个服务器。

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_KEEPALIVEtrue); // (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;

        if (args.length > 0) {

            port = Integer.parseInt(args[0]);

        } else {

            port = 8080;

        }

        new DiscardServer(port).run();

    }

}

1. NioEventLoopGroup 是一个多线程的事件循环,处理IO操作。

 Netty提供了各种各样的 EventLoopGroup实现来应对不同种类的传输。

我们在例子中实现服务器端的工程,因此两个NioEventLoopGroup 将会被使用,第一个,经常叫做boss,接收一个进来的连接,第二个,叫做worker,处理流量(接受的连接)一旦 boss接收了连接并且注册接收的连接到worker.多少线程被使用并且它们如何映射到创建的Channels依赖于 EventLoopGroup 实现,也可以通过构造器配置。

2. ServerBootstrap 是一个帮助类来安装服务器,你可以通过Channel来直接安装。

3. 尽管如此,要知道,这是一个单调的过程,大多数情况下不需要做这个。

4. 这里,我们使用了 NioServerSocketChannel 类来初始化一个新的Channel来接收进来的连接。这个handler总是被新接受的channel调用。

5. ChannelInitializer是一个特别的handler,目的是帮助一个用户来配置一个新的Channel最有可能的就是你想配置 ChannelPipeline of the new Channel 通过增加新的句柄方法比如DiscardServerHandler 来实现你的网络工程。

6. 一旦工程变复杂了,你将增加更多的方法到pipeline上来,提取这个匿名类到一个底层类里。

7. 你也可以设置参数(特定于channel实现),我们在写一个TCP/IP服务器,所以我们可以设置socket的参数比如tcpNoDelay and keepAlive

8. 请参考ChannelOption 和特定的ChannelConfig实现来获取支持的选项说明。

9. 你意识到option()和childOption()?

10.  option()是为了NioServerSocketChannel ,这个接受连接。childOption()是为了channels(被父ServerChannel接受 ,在例子当中是 NioServerSocketChannel 

11. 我们准备好了,剩下的就是绑定端口和启动服务器,这里,我们绑定到8080端口,你可以调用bind()方法任意多次只要愿意。(可以以不同的绑定定制).

祝贺,你已经完成了第一个服务器的开发。

 

翻译 ok ok ok
理解 ok ok ok

 

你可能感兴趣的:(netty)