www.zhblog.net

Netty TCP Hello 实例

TCP Server

Netty的服务之一是TCP服务。要创建Netty TCP服务,必须: 

创建一个EventLoopGroup 

创建和配置ServerBootstrap 

创建一个ChannelInitializer 

启动服务器


这是一个代码示例,显示了如何创建Netty TCP服务:

EventLoopGroup group = new NioEventLoopGroup();



try{

    ServerBootstrap serverBootstrap = new ServerBootstrap();

    serverBootstrap.group(group);

    serverBootstrap.channel(NioServerSocketChannel.class);

    serverBootstrap.localAddress(new InetSocketAddress("localhost", 9999));



    serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

        protected void initChannel(SocketChannel socketChannel) throws Exception {

            socketChannel.pipeline().addLast(new HelloServerHandler());

        }

    });

    ChannelFuture channelFuture = serverBootstrap.bind().sync();

    channelFuture.channel().closeFuture().sync();

} catch(Exception e){

    e.printStackTrace();

} finally {

    group.shutdownGracefully().sync();

}


创建一个EventLoopGroup 

创建Netty TCP服务的第一步是创建Netty EventLoopGroup。示例使用 NIO,因此创建了NioEventLoopGroup。这是创建EventLoopGroup的代码:

EventLoopGroup group = new NioEventLoopGroup();


创建一个ServerBootStrap 

创建Netty TCP服务的下一步是创建和配置ServerBootStrap。使用以下行完成此操作:

ServerBootstrap serverBootstrap = new ServerBootstrap();

serverBootstrap.group(group);

serverBootstrap.channel(NioServerSocketChannel.class);

serverBootstrap.localAddress(new InetSocketAddress("localhost", 9999));


首先,创建一个ServerBootstrap实例。 其次,在ServerBootstrap实例上设置EventLoopGroup。 第三,在ServerBootstrap实例上设置NioServerSocketChannel类实例。这是必需的,因为该示例使用了NioEventLoopGroup。 第四,在ServerBootstrap上设置本地IP地址/域+ TCP端口。要启动Netty TCP服务器,这也是必需设置的。


创建一个ChannelInitializer 

启动Netty TCP服务的第三步是创建ChannelInitializer并将其附加到ServerBootstrap实例。 ChannelInitializer初始化所有传入TCP连接的套接字。 在以下行中创建并附加ChannelInitializer:

serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

    protected void initChannel(SocketChannel socketChannel) throws Exception {

        socketChannel.pipeline().addLast(new HelloServerHandler());

    }

});


Netty ChannelInitializer类是一个抽象类。每当TCP服务器接受新的传入TCP连接时,就会调用其方法initChannel()。它将新的HelloServerHandler(一个ChannelHandler)附加到每个新的SocketChannel。还可以在所有新的SocketChannel实例中重用相同的ChannelHandler,而不是每次都在此处创建新的实例。使用childHandler()方法将ChannelInitializer添加到ServerBootstrap中。之所以将其称为“子”处理程序,是因为每个接受的SocketChannel被视为接受它的服务器套接字的“子”。


启动服务器 

引导Netty TCP服务的最后一步是启动服务:

ChannelFuture channelFuture = serverBootstrap.bind().sync();


serverBootstrap.bind()方法返回一个ChannelFuture,可用于了解何时完成服务器绑定(绑定到本地地址和TCP端口)。通过在ChannelFuture上调用sync(),创建服务的主线程将等到服务启动后再继续。顺便说一下,sync()方法还返回ChannelFuture。


HelloServerHandler

ChannelInitializer添加到每个SocketChannel的HelloServerHandler是处理来自客户端连接的传入数据的组件:

public class HelloServerHandler extends ChannelInboundHandlerAdapter {



    @Override

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf inBuffer = (ByteBuf) msg;



        String received = inBuffer.toString(CharsetUtil.UTF_8);

        System.out.println("Server received: " + received);



        ctx.write(Unpooled.copiedBuffer("Hello " + received, CharsetUtil.UTF_8));

    }



    @Override

    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)

                .addListener(ChannelFutureListener.CLOSE);

    }



    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        cause.printStackTrace();

        ctx.close();

    }

}


每当从HelloServerHandler实例附加到的SocketChannel接收数据时,都会调用channelRead()方法。客户端发送到服务器的任何内容,​​channelRead()都会以“ Hello” + 响应。 当没有更多数据可从SocketChannel中读取时,调用channelReadComplete()方法。 如果从SocketChannel接收或发送数据时引发异常,则调用exceptionCaught()方法。在这里,决定应如何处理异常后事情,例如关闭连接或使用错误代码进行响应等。


TCP Client

Netty也可以用于创建TCP客户端。在本教程中,要使用Netty创建TCP客户端,需要: 

创建一个EventLoopGroup 

创建和配置引导程序 Bootstrap

创建一个ChannelInitializer 启动客户端


EventLoopGroup group = new NioEventLoopGroup();

try{

    Bootstrap clientBootstrap = new Bootstrap();



    clientBootstrap.group(group);

    clientBootstrap.channel(NioSocketChannel.class);

    clientBootstrap.remoteAddress(new InetSocketAddress("localhost", 9999));

    clientBootstrap.handler(new ChannelInitializer<SocketChannel>() {

        protected void initChannel(SocketChannel socketChannel) throws Exception {

            socketChannel.pipeline().addLast(new ClientHandler());

        }

    });

    ChannelFuture channelFuture = clientBootstrap.connect().sync();

    channelFuture.channel().closeFuture().sync();

} finally {

    group.shutdownGracefully().sync();

}


创建一个EventLoopGroup 

创建Netty TCP客户端的第一步是创建Netty EventLoopGroup。示例使用 NIO,因此创建了NioEventLoopGroup:

EventLoopGroup group = new NioEventLoopGroup();


创建和配置Bootstrap

使用Netty创建TCP客户端的第二步是创建Netty Bootstrap实例。请注意,TCP服务使用ServerBootstrap,而TCP客户端使用Bootstrap实例:

Bootstrap clientBootstrap = new Bootstrap();


还必须配置Bootstrap实例:

clientBootstrap.group(group);

clientBootstrap.channel(NioSocketChannel.class);

clientBootstrap.remoteAddress(new InetSocketAddress("localhost", 9999));


这在Bootstrap实例上设置EventLoopGroup,指定Bootstrap实例使用NIO,并设置要连接的远程IP地址和TCP端口。


创建一个ChannelInitializer 

创建Netty TCP客户端的第三步是创建ChannelInitializer并将其附加到Bootstrap实例:

clientBootstrap.handler(new ChannelInitializer<SocketChannel>() {

    protected void initChannel(SocketChannel socketChannel) throws Exception {

        socketChannel.pipeline().addLast(new ClientHandler());

    }

});


ChannelInitializer将ClientHandler实例附加到它创建的SocketChannel。每当从附加到其的SocketChannel接收到数据时,就会调用ClientHandler。 ClientHandler附加到SocketChannel的管道。


启动客户端 

创建Netty TCP客户端的最后一步是启动TCP客户端:

ChannelFuture channelFuture = clientBootstrap.connect().sync();


此Bootstrap实例连接到远程服务器,并等待直到连接成功为止:

channelFuture.channel().closeFuture().sync();


ClientHandler 

附加到连接到远程服务器的SocketChannel的ClientHandler包含实际的客户端行为:

public class ClientHandler extends SimpleChannelInboundHandler {



    @Override

    public void channelActive(ChannelHandlerContext channelHandlerContext){

        channelHandlerContext.writeAndFlush(Unpooled.copiedBuffer("Netty Rocks!", CharsetUtil.UTF_8));

    }



    @Override

    public void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf in) {

        System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8));

    }



    @Override

    public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable cause){

        cause.printStackTrace();

        channelHandlerContext.close();

    }

}


至此,一个简单的 Netty TCP 服务就完成了!


 

展开阅读全文

评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 心情