深入浅出Netty之四 Client请求处理

前2篇分析了echo server端的运行机制,本篇同样以echo client为例,分析netty的nio客户端的运行机制。
总体来说client端和server端的处理是类似的,NioWorker是重用的,也就意味着client和server的读写机制是一样的,都是通过worker线程来管理的。所不同的是Boss线程,server端的boss线程一个bind端口起一个,主要负责接收新请求,而client端的boss线程是一个可配置的数组,一个connect端口分配一个,主要负责connect过程,如果connect成功则将channle注册到worker线程中处理。在Client同样有PipelineSink,叫做NioClientSocketPipelineSink,也是负责底层IO和pipeline之间的交互。
EchoClient代码:
Java代码 复制代码 收藏代码
  1. // 初始化Bootstrap和NioClientSocketChannelFactory,这一步将启动nioWorker线程,并初始化NioClientSocketPipelineSink,并将Boss线程创建
  2. ClientBootstrap bootstrap = new ClientBootstrap(
  3. new NioClientSocketChannelFactory(
  4. Executors.newCachedThreadPool(),
  5. Executors.newCachedThreadPool()));
  6. // 用户自定义的pipeline工厂
  7. bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
  8. public ChannelPipeline getPipeline() throws Exception {
  9. return Channels.pipeline(
  10. new EchoClientHandler(firstMessageSize));
  11. }
  12. });
  13. // 异步创建连接
  14. ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
  15. //等待连接关闭
  16. future.getChannel().getCloseFuture().awaitUninterruptibly();
  17. // 关闭资源,线程池等
  18. bootstrap.releaseExternalResources();
        // 初始化Bootstrap和NioClientSocketChannelFactory,这一步将启动nioWorker线程,并初始化NioClientSocketPipelineSink,并将Boss线程创建
          ClientBootstrap bootstrap = new ClientBootstrap(
                  new NioClientSocketChannelFactory(
                          Executors.newCachedThreadPool(),
                          Executors.newCachedThreadPool()));
  
          // 用户自定义的pipeline工厂
          bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
              public ChannelPipeline getPipeline() throws Exception {
                  return Channels.pipeline(
                          new EchoClientHandler(firstMessageSize));
              }
          });
  
          // 异步创建连接
          ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
  
          //等待连接关闭
          future.getChannel().getCloseFuture().awaitUninterruptibly();
  
          // 关闭资源,线程池等
          bootstrap.releaseExternalResources();
具体connect过程:
一.创建client的channel
Java代码 复制代码 收藏代码
  1. public ChannelFuture connect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
  2. ......
  3. //拿用户自定义的pipeline
  4. ChannelPipeline pipeline;
  5. try {
  6. pipeline = getPipelineFactory().getPipeline();
  7. } catch (Exception e) {
  8. throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
  9. }
  10. // 从ChannelFactory中,创建Channel,对于client来说factory是NioClientSocketChannelFactory,Channel是NioClientSocketChannel
  11. Channel ch = getFactory().newChannel(pipeline);
  12. // 通过channel连接
  13. return ch.connect(remoteAddress);
  14. }
public ChannelFuture connect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
	......
	//拿用户自定义的pipeline
        ChannelPipeline pipeline;
        try {
            pipeline = getPipelineFactory().getPipeline();
        } catch (Exception e) {
            throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
        }
        // 从ChannelFactory中,创建Channel,对于client来说factory是NioClientSocketChannelFactory,Channel是NioClientSocketChannel
        Channel ch = getFactory().newChannel(pipeline);
        // 通过channel连接
        return ch.connect(remoteAddress);
    }
二.创建channel时,分配worker
Java代码 复制代码 收藏代码
  1. public SocketChannel newChannel(ChannelPipeline pipeline) {
  2. return new NioClientSocketChannel(this, pipeline, sink, sink.nextWorker());
  3. }
 public SocketChannel newChannel(ChannelPipeline pipeline) {
        return new NioClientSocketChannel(this, pipeline, sink, sink.nextWorker());
    }
三.创建内部的SocketChannel,触发ChannelOpen事件,不过echo client的handler没有对channelOpen事件做处理

你可能感兴趣的:(java,的,桃子)