photo-of-woman-reading-book-3747468.jpg
前言:
一直在零零碎碎的看关于netty的源码和《netty实战》,也一直想记录下自己的学习过程,但是由于种种原因,一直没写。万事开头难,一旦开个头,剩下的就只剩坚持了。不要等着什么都准备好,才去下笔,不要有太多的虚荣心,要更实事求是一点。只要自己稍微有点想法,就可以记录下来,刚开始可能写的不完善,不深入,但是日积月累,量变引起质变,所有的事情都有个发展过程,要遵循客观的自然规律。
简介:
相当于一个工具类,用来创建客户端Channel和发起连接请求。还可以配置一些channel的属性,channel其实就是对底层socket的抽象封装,简化、统一了一些操作。
API:
public class ClientBootstrap extends Bootstrap {
public ClientBootstrap() {//构造一个不指定ChannelFactory的Bootstrap,在后续代码里set
super();
}
public ClientBootstrap(ChannelFactory channelFactory) {//构造一个指定ChannelFactory的Bootstrap
super(channelFactory);
}
public ChannelFuture connect() {
SocketAddress remoteAddress = (SocketAddress) getOption("remoteAddress");
if (remoteAddress == null) {
throw new IllegalStateException("remoteAddress option is not set.");
}
return connect(remoteAddress);
}
public ChannelFuture connect(SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remotedAddress");
}
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
return connect(remoteAddress, localAddress);
}
public ChannelFuture connect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
final BlockingQueue<ChannelFuture> futureQueue =
new LinkedBlockingQueue<ChannelFuture>();//保存channel连接remoteAddress的异步结果
ChannelPipeline pipeline;
try {
pipeline = getPipelineFactory().getPipeline();
} catch (Exception e) {
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
}
pipeline.addFirst(
"connector", new Connector(
this, remoteAddress, localAddress, futureQueue));//向pipeline里面添加一个handler
getFactory().newChannel(pipeline);//@1:new channel() 这个方法里面做的事情还是不少的,下面会继续跟踪一下的。
// Wait until the future is available.
ChannelFuture future = null;
do {
try {
future = futureQueue.poll(Integer.MAX_VALUE, TimeUnit.SECONDS);//从队列取出可用的ChannelFuture,如果没有可用的,会暂时阻塞住
} catch (InterruptedException e) {
// Ignore
}
} while (future == null);
pipeline.remove("connector");//程序结束,从pipeline里面移除handler
return future;
}
@ChannelPipelineCoverage("one")//表示是否线程安全
static final class Connector extends SimpleChannelUpstreamHandler {
private final Bootstrap bootstrap;
private final SocketAddress localAddress;
private final BlockingQueue<ChannelFuture> futureQueue;
private final SocketAddress remoteAddress;
private volatile boolean finished = false;
Connector(
Bootstrap bootstrap,
SocketAddress remoteAddress,
SocketAddress localAddress,
BlockingQueue<ChannelFuture> futureQueue) {
this.bootstrap = bootstrap;
this.localAddress = localAddress;
this.futureQueue = futureQueue;
this.remoteAddress = remoteAddress;
}
@Override
public void channelOpen(
ChannelHandlerContext context,
ChannelStateEvent event) {
try {
// Apply options.
event.getChannel().getConfig().setOptions(bootstrap.getOptions());
} finally {
context.sendUpstream(event);
}
// Bind or connect.
if (localAddress != null) {
event.getChannel().bind(localAddress);
} else {
finished = futureQueue.offer(event.getChannel().connect(remoteAddress));
assert finished;
}
}
@Override
public void channelBound(
ChannelHandlerContext context,
ChannelStateEvent event) {
context.sendUpstream(event);
// Connect if not connected yet.
if (localAddress != null) {
finished = futureQueue.offer(event.getChannel().connect(remoteAddress));
assert finished;
}
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
ctx.sendUpstream(e);
Throwable cause = e.getCause();
if (!(cause instanceof NotYetConnectedException) && !finished) {
e.getChannel().close();
finished = futureQueue.offer(failedFuture(e.getChannel(), cause));
assert finished;
}
}
}
}
分析:
@1处的newChannel()方法的目的是构造一个客户端的channel,也就是NioClientSocketChannel,在NioClientSocketChannel的构造方法里面有一句代码:fireChannelOpen(this);这个方法用来触发ChannelPipeLine中的第一个handler,其实也就是继承于SimpleChannelUpstreamHandler的Connector类,也算是一个handler,用来开启HandlerPipeLine上的handler流水线。紧接着是sendUpstream()这个方法,最终会调用SimpleChannelHandler的handleUpstream()方法,这个方法主要负责把对应流的事件向下传递给子事件、并且调用适当的handler来继续处理......后续还会触发Connect事件......感觉逻辑挺多的,暂停一下,一口吃不了一个胖子。
总结:
netty的源码还是需要尽快投入精力和时间去好好研究一下,不然没有质的提升呀,加油呀,还有好多源码等着看呢......。










网友评论