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执行流程
这里写图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值