Netty學習之客戶端建立

1、客戶端開發時序圖

  

  圖片來源:Netty權威指南(第2版)html

2、Netty客戶端開發步驟

  使用Netty進行客戶端開發主要有如下幾個步驟:bootstrap

  一、用戶線程建立Bootstrap

Bootstrap b = new Bootstrap();

  Bootstrap是Socket客戶端建立工具類,經過API設置建立客戶端相關的參數,異步發起客戶端鏈接。服務器

  二、建立處理客戶端鏈接、IO讀寫的Reactor線程組NioEventLoopGroup

EventLoopGroup group = new NioEventLoopGroup();

  三、經過Bootstrap的ChannelFactory和用戶指定的Channel類型建立用於客戶端鏈接的NioSocketChannel

b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)

  此處的NioSocketChannel相似於Java NIO提供的SocketChannel。網絡

  四、建立默認的channel Handler pipeline

b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
 .handler(new ChannelInitializer<SocketChannel>()
  {
       @Override
       public void initChannel(SocketChannel ch) throws Exception
       {
         ch.pipeline().addLast(new HelloClientHandler());
        }
  });

  用於調度和執行網絡事件。異步

  五、異步發起TCP鏈接

 // 發起異步鏈接操做
 ChannelFuture f = b.connect(host, port).sync();

  SocketChannel執行connect()操做後有如下三種結果:socket

  • 鏈接成功,然會true;
  • 暫時沒有鏈接上,服務器端沒有返回ACK應答,鏈接結果不肯定,返回false。此種結果下,須要將NioSocketChannel中的selectionKey設置爲OP_CONNECT,監聽鏈接結果;
  • 接連失敗,直接拋出I/O異常

  六、由多路複用器在I/O中輪詢個Channel,處理鏈接結果

  七、若是鏈接成功,設置Future結果,發送鏈接成功事件,觸發ChannelPipeline執行

  八、由ChannelPipeline調度執行系統和用戶的ChannelHandler,執行業務邏輯

3、Netty客戶端開發示例代碼

  需求:客戶端端實現,鏈接服務器端,並向服務器端發送hello Netty。(注:本代碼使用的netty是netty-all-5.0.0.Alpha1-sources.jar版本)ide

  服務器端代碼見Netty學習之服務器端建立工具

  客戶端代碼:oop

import io.netty.bootstrap.Bootstrap;
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.NioSocketChannel;

public class HelloClient
{
    public void connect(int port, String host) throws Exception
    {
        // 配置客戶端NIO線程組
        EventLoopGroup group = new NioEventLoopGroup();
        try
        {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>()
                    {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception
                        {
                            ch.pipeline().addLast(new HelloClientHandler());
                        }
                    });

            // 發起異步鏈接操做
            ChannelFuture f = b.connect(host, port).sync();

            // 等待客戶端鏈路關閉
            f.channel().closeFuture().sync();
        } finally
        {
            group.shutdownGracefully();
        }
    }
    public static void main(String[] args) throws Exception
    {
        int port = 8080;
        new HelloClient().connect(port, "127.0.0.1");
    }
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class HelloClientHandler  extends ChannelHandlerAdapter
{

    private final ByteBuf message;
    
    public HelloClientHandler()
    {
        byte[] req="hello Netty".getBytes();
        message=Unpooled.buffer(req.length);
        message.writeBytes(req);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception
    {
        ctx.writeAndFlush(message);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
    {
        ctx.close();
    }
}

  程序運行結果:學習

  

4、參考資料

  一、Netty權威指南

相關文章
相關標籤/搜索