您的位置:首页 > Web前端 > BootStrap

Netty源码分析:ServerBootstrap

2017-09-23 23:39 896 查看

Netty源码分析:ServerBootstrap

一般服务端的代码如下所示:

package com.wrh.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
* Created by wuranghao on 2017/9/4.
*/
public final class SimpleServer {

public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new SimpleServerHandler())
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
}
});

ChannelFuture f = b.bind(8888).sync();

f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

private static class SimpleServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
}

@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelRegistered");
}

@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded");
}
}
}


在上篇博文(http://blog.csdn.net/u010412719/article/details/78006968)中 剖析了如下的两行代码内部的构造函数中干了些什么。

EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();


具体可以见上篇博文,对于如上的两行代码得到的结论是:

1、 如果不指定线程数,则线程数为:CPU的核数*2

2、根据线程个数是否为2的幂次方,采用不同策略初始化chooser

3、产生nThreads个NioEventLoop对象保存在children数组中。

可以理解NioEventLoop就是一个线程,线程NioEventLoop中里面有如下几个属性:

1、NioEventLoopGroup (在父类SingleThreadEventExecutor中)

2、selector

3、provider

4、thread (在父类SingleThreadEventExecutor中)

更通俗点就是: NioEventLoopGroup就是一个线程池,NioEventLoop就是一个线程。NioEventLoopGroup线程池中有N个NioEventLoop线程。

ServerBootstrap类分析

本篇博文将分析如下几行代码里面做了些什么。

ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new SimpleServerHandler())
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
}
});


ServerBootstrap类的继承结构如下:



该类的参数,有必要列出:

private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
private volatile EventLoopGroup childGroup;
private volatile ChannelHandler childHandler;


其父类AbstractBootstrap的参数

private volatile EventLoopGroup group;
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;


ServerBootstrap类的无参构造函数什么都没有做,这没什么好说的。下面主要看下这个链式设置相关的参数。

1)group(bossGroup, workerGroup):设置group

public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}


即将workerGroup保存在 ServerBootstrap对象的childGroup属性上。 bossGroup保存在ServerBootstrap对象的group属性上

2)channel(NioServerSocketChannel.class)

public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new BootstrapChannelFactory<C>(channelClass));
}
public B channelFactory(ChannelFactory<? extends C> channelFactory) {
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
}
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}

this.channelFactory = channelFactory;
return (B) this;
}


函数功能:设置父类属性channelFactory 为: BootstrapChannelFactory类的对象。其中这里BootstrapChannelFactory对象中包括一个clazz属性为:NioServerSocketChannel.class,从如下该类的构造函数中可以明显的得到这一点。

private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Class<? extends T> clazz;

BootstrapChannelFactory(Class<? extends T> clazz) {
this.clazz = clazz;
}

@Override
public T newChannel() {
try {
return clazz.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}

@Override
public String toString() {
return StringUtil.simpleClassName(clazz) + ".class";
}
}


3)handler(new SimpleServerHandler())

此方法的具体代码如下:

public B handler(ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
this.handler = handler;
return (B) this;
}


函数功能:设置handler属性,该属性在其父类 AbstractBootstrap中。

注意:这里的handler函数的入参类是我们自己提供的。如下,后面的博文中将会分析这个handler将会在哪里以及何时被调用,这里只需要记住这一点即可

private static class SimpleServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
}

@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelRegistered");
}

@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded");
}
}


4)childHandler

public ServerBootstrap childHandler(ChannelHandler childHandler) {
if (childHandler == null) {
throw new NullPointerException("childHandler");
}
this.childHandler = childHandler;
return this;
}


简单来说就是将如下的childHandler设置在AbstractBootstrap的相应属性上。

childHandler = new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
}
})


总结

比较简单哈,主要是将我们提供的参数设置到其相应的对象属性中去了。 因为后面会用到如下的几个属性,因此最好知道下,这些属性是何时以及在那里赋值的。以免分析到后面会很懵逼。

1、group:workerGroup保存在 ServerBootstrap对象的childGroup属性上。 bossGroup保存在ServerBootstrap对象的group属性上

2、channelFactory:BootstrapChannelFactory类的对象(clazz属性为:NioServerSocketChannel.class)

3、handler:SimpleServerHandler

4、childHandler
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: