You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(1) new InetSocketAddress(String hostname, int port)
根据主机名和端口创建InetSocketAddress,指远程连接的地址和端口
(2) bootstrap.connect调用doResolveAndConnect,重要的有两步initAndRegister和doResolveAndConnect0,而initAndRegister包括init和register
private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
//重点分析
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.isDone()) {
if (!regFuture.isSuccess()) {
return regFuture;
}
return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise());
} else {
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
promise.setFailure(cause);
} else {
promise.registered();
doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
}
}
});
return promise;
}
}
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
}
}
}
上面包含register0方法调用下面的:
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// Force the Selector to select now as the "canceled" SelectionKey may still be
// cached and not removed because no Select.select(..) operation was called yet.
eventLoop().selectNow();
selected = true;
} else {
// We forced a select operation on the selector before but the SelectionKey is still cached
// for whatever reason. JDK bug ?
throw e;
}
}
}
}
启动代码
分析代码
1. NioEventLoopGroup worker = new NioEventLoopGroup()
创建线程组处理客户端事件,具体过程同服务端#2
2. Bootstrap bootstrap = new Bootstrap()
创建启动类
3. bootstrap.group(worker)
设置线程组到启动类
4. bootstrap.channel(NioSocketChannel.class)
内部基于NioSocketChannel创建ChannelFactory,ChannelFactory可以生成NioSocketChannel
5. bootstrap.handler
添加handler处理具体的事件,业务逻辑就写在各handler中
6. ChannelFuture future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8866)).sync()
(1) new InetSocketAddress(String hostname, int port)
根据主机名和端口创建InetSocketAddress,指远程连接的地址和端口
(2) bootstrap.connect调用doResolveAndConnect,重要的有两步initAndRegister和doResolveAndConnect0,而initAndRegister包括init和register
(3)init方法中包括重要的p.addLast(config.handler()),即在ChannelPipeline中添加handler
p.addLast(config.handler())方法调用下面的addLast
其中newCtx = newContext(group, filterName(name, handler), handler)是将hanlder封装到ChannelHandlerContext中; addLast0(newCtx)是将ChannelHandlerContext添加到handler中。
(4) register中有一行代码AbstractChannel.this.eventLoop = eventLoop即将线程组放到Channel中,而Channel创建的时候已经绑定了ChannelPipeline,这样Channel中指定了所用的处理线程池eventLoop,同时绑定了ChannelPipeline,而ChannelPipeline中持有了许多ChannelHandler,每个ChannelHandler有自己的ChannelHandlerContext。
上面包含register0方法调用下面的:
javaChannel().register(eventLoop().unwrappedSelector(), 0, this)此处是将java.nio.channels.ServerSocketChannel注册到java.nio.channels.Selector上,已经调试到jdk的代码了
(5) doResolveAndConnect0调用下面的
SocketUtils.connect(javaChannel(), remoteAddress)调用java.nio.channels.SocketChannel#connect(java.net.SocketAddress)方法连接远程地址
7. future.channel().closeFuture().sync()
阻塞线程直到客户端关闭
作者原创,转载请注明出处,违法必究!
The text was updated successfully, but these errors were encountered: