转载-Netty教程-Bootstrap类介绍

Bootstrap介绍

 Bootstrap是开发netty客户端的基础,通过Bootstrap的connect方法来连接服务器端。该方法返回的也是ChannelFuture,
 通过这个我们可以判断客户端是否连接成功,以便我们在连接成功之后,做一些其他的事情。但是在调用connect方法前,
 我们需要指定EventLoopGroup,channelFactory(不指定这个,就会使用netty默认的channelFactory,但是需要指定channel,初始channel时,
 同时会初始化channelFactory),ChannelHandler。这些都是必须指定的,不指定就会报异常.例如不指定channel和channelFactory,
 就会报下面的错误。

 

 

这里写图片描述

Bootstrap继承结构

这里写图片描述

构建Bootstrap

public final class EchoClient {

    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
    static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
    /** 与server连接的channel */
    private static Channel channel;

    public static void main(String[] args) throws Exception {
        // Configure the client.
        EventLoopGroup group = new NioEventLoopGroup();
        try {
             Bootstrap b = new Bootstrap();
             b.group(group)
             //不指定channelFactory,就需要指定channel,channel初始化时会指定默认的channelFactory。
             .channel(NioSocketChannel.class)
             //指定channelFactory,就不需要指定channel了。
             //.channelFactory(new ReflectiveChannelFactory<Channel>(NioSocketChannel.class))
             .option(ChannelOption.TCP_NODELAY, true)
             //指定ChannelHandler
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     p.addLast(new EchoClientHandler());
                 }
             });

            // Start the client.
           b.connect(HOST, PORT).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if( future.isSuccess() ){
                        channel=future.channel();
                    } else {
                    }
                }
            });         
            while(true){
                if(channel!=null && channel.isActive()){
                    ByteBuf buff = channel.alloc().buffer(64);
                    buff.writeByte(1);
                    ChannelFuture channelFuture = channel.writeAndFlush(buff);
                    channelFuture.addListener(new ChannelFutureListener() {          
                        // write操作完成后调用的回调函数  
                        @Override  
                        public void operationComplete(ChannelFuture future) throws Exception {  
                            if(future.isSuccess()) { // 是否成功  
                                System.out.println("客户端write操作成功");  
                            } else {  
                                System.out.println("客户端write操作失败");  
                            }  
                        }                    
                    });
                }else{
                    System.out.println("客户端已经断开连接");
                }
            }
        }  finally {
            group.shutdownGracefully();
        } 
    }
}

 

介绍下上面代码涉及到的类: 
EventLoop 这个相当于一个处理线程,是Netty接收请求和处理IO请求的线程。 
EventLoopGroup 可以理解为将多个EventLoop进行分组管理的一个类,是EventLoop的一个组。 
ChannelPipeline 这是Netty处理请求的责任链,这是一个ChannelHandler的链表,而ChannelHandler就是用来处理网络请求的内容的。 
ChannelHandler 用来处理网络请求内容,有ChannelInboundHandler和ChannelOutboundHandler两种,ChannlPipeline会从头到尾顺序调用ChannelInboundHandler处理网络请求内容,从尾到头调用ChannelOutboundHandler处理网络请求内容。这也是Netty用来灵活处理网络请求的机制之一,因为使用的时候可以用多个decoder和encoder进行组合,从而适应不同的网络协议。而且这种类似分层的方式可以让每一个Handler专注于处理自己的任务而不用管上下游,这也是pipeline机制的特点。这跟TCP/IP协议中的五层和七层的分层机制有异曲同工之妙。 
ChannelFuture 
在Netty中的所有的I/O操作都是异步执行的,这就意味着任何一个I/O操作会立刻返回,不保证在调用结束的时候操作会执行完成。因此,会返回一个ChannelFuture的实例,通过这个实例可以获取当前I/O操作的状态。

option设置的参数:

SO_RCVBUF ,SO_SNDBUF 
每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。 
这两个选项就是来设置TCP连接的两个buffer尺寸的。 
SO_SNDBUF 
  Socket参数,TCP数据发送缓冲区大小。该缓冲区即TCP发送滑动窗口,linux操作系统可使用命令:cat /proc/sys/net/ipv4/tcp_smem查询其大小。 
TCP_NODELAY 
  TCP参数,立即发送数据,默认值为Ture(Netty默认为True而操作系统默认为False)。该值设置Nagle算法的启用,改算法将小的碎片数据连接成更大的报 
文来最小化所发送的报文的数量,如果需要发送一些较小的报文,则需要禁用该算法。Netty默认禁用该算法,从而最小化报文传输延时。 
SO_KEEPALIVE 
  Socket参数,连接保活,默认值为False。启用该功能时,TCP会主动探测空闲连接的有效性。可以将此功能视为TCP的心跳机制,需要注意的是:默认的心跳间隔是7200s即2小时。Netty默认关闭该功能。 
SO_REUSEADDR 
  Socket参数,地址复用,默认值False。有四种情况可以使用: 
(1).当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你希望启动的程序 
的socket2要占用该地址和端口,比如重启服务且保持先前端口。 
(2).有多块网卡或用IP Alias技术的机器在同一端口启动多个进程,但每个进程绑定的本地IP地址不能相同。 
(3).单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。(4).完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。 
SO_LINGER 
  Socket参数,关闭Socket的延迟时间,默认值为-1,表示禁用该功能。-1表示socket.close()方法立即返回,但OS底层会将发送缓冲区全部发送到对端。0表示socket.close()方法立即返回,OS放弃发送缓冲区的数据直接向对端发送RST包,对端收到复位错误。非0整数值表示调用socket.close()方法的线程被阻塞直到延迟时间到或发送缓冲区中的数据发送完毕,若超时,则对端会收到复位错误。 
SO_BACKLOG 
  Socket参数,服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝。默认值,Windows为200,其他为128。 
SO_BROADCAST 
  Socket参数,设置广播模式。

Bootstrap执行流程

为了弄清楚Bootstrap如何工作,我们先介绍下AbstractBootstrap:

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
    volatile EventLoopGroup group;
    @SuppressWarnings("deprecation")
    private volatile ChannelFactory<? extends C> channelFactory;
    private volatile SocketAddress localAddress;
    private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
    private volatile ChannelHandler handler;

 

 

从上面代码可以看出,AbstractBootstrap包含6个属性,这些属性,在我们调用connect方法时,会使用到,我们可以使用一下方法来设置这几个属性的值。

    public B group(EventLoopGroup group)
    public B channel(Class<? extends C> channelClass)
    public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory)
    public B localAddress(SocketAddress localAddress)
    public B localAddress(int inetPort)
    public B localAddress(String inetHost, int inetPort) 
    public B localAddress(InetAddress inetHost, int inetPort)
    public <T> B option(ChannelOption<T> option, T value)
    public <T> B attr(AttributeKey<T> key, T value)
    public B handler(ChannelHandler handler)

 

Bootstrap执行流程 
这里写图片描述

 

转载自:http://blog.csdn.net/woaixiaopangniu521/article/details/70242422

posted @ 2018-03-06 10:18  和美信息叶育生博文  阅读(505)  评论(0编辑  收藏  举报