ChannelFuture
channel的操作因为都是异步的,因此大部分都返回channelFuture 例如wirte方法。有两个版本一个是,可以传参ChannelPromise另一个是不能传
*/
ChannelFuture write(Object msg);
/**
* Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}.
* This method will not request to actual flush, so be sure to call {@link #flush()}
* once you want to request to flush all pending data to the actual transport.
*/
ChannelFuture write(Object msg, ChannelPromise promise);
如果不穿,netty会自动帮我们创建一个Promise
public class DefaultChannelPromise extends DefaultPromise<Void> implements ChannelPromise, FlushCheckpoint {
private final Channel channel;
private long checkpoint;
/**
* Creates a new instance.
*
* @param channel
* the {@link Channel} associated with this future
*/
public DefaultChannelPromise(Channel channel) {
this.channel = channel;
}
/**
* Creates a new instance.
*
* @param channel
* the {@link Channel} associated with this future
*/
public DefaultChannelPromise(Channel channel, EventExecutor executor) {
super(executor);
this.channel = channel;
}
@Override
protected EventExecutor executor() {
EventExecutor e = super.executor();
if (e == null) {
return channel().eventLoop();
} else {
return e;
}
}
@Override
public Channel channel() {
return channel;
}
@Override
public ChannelPromise setSuccess() {
return setSuccess(null);
}
@Override
public ChannelPromise setSuccess(Void result) {
super.setSuccess(result);
return this;
}
@Override
public boolean trySuccess() {
return trySuccess(null);
}
@Override
public ChannelPromise setFailure(Throwable cause) {
super.setFailure(cause);
return this;
}
@Override
public ChannelPromise addListener(GenericFutureListener<? extends Future<? super Void>> listener) {
super.addListener(listener);
return this;
}
@Override
public ChannelPromise addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
super.addListeners(listeners);
return this;
}
@Override
public ChannelPromise removeListener(GenericFutureListener<? extends Future<? super Void>> listener) {
super.removeListener(listener);
return this;
}
@Override
public ChannelPromise removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners) {
super.removeListeners(listeners);
return this;
}
@Override
public ChannelPromise sync() throws InterruptedException {
super.sync();
return this;
}
@Override
public ChannelPromise syncUninterruptibly() {
super.syncUninterruptibly();
return this;
}
@Override
public ChannelPromise await() throws InterruptedException {
super.await();
return this;
}
@Override
public ChannelPromise awaitUninterruptibly() {
super.awaitUninterruptibly();
return this;
}
@Override
public long flushCheckpoint() {
return checkpoint;
}
@Override
public void flushCheckpoint(long checkpoint) {
this.checkpoint = checkpoint;
}
@Override
public ChannelPromise promise() {
return this;
}
@Override
protected void checkDeadLock() {
if (channel().isRegistered()) {
super.checkDeadLock();
}
}
@Override
public ChannelPromise unvoid() {
return this;
}
@Override
public boolean isVoid() {
return false;
}
}
常规用法
一般的用法为
ChannelFuture future = bootstrap.connect("localhost", 8888).sync();
等待同步执行。如果需要等待操作成功后在继续周性,就调用.sync();
channel.writeAndFlush(br.readLine() + "\n").addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
System.out.println("ss");
}
});
注册监听方法等待执行成功时回调
特殊回调时机
connect 在connect执行之后,收到服务端的确认后才是建立连接成功。才会调用回调 write回调时机时flush将outbuff调用socket写之后回调,不能保证对方可以收到 close 在socket关闭时调用,完成前二次挥手
closeFuture
我们一般在server端最后加这么一句话
future.channel().closeFuture().sync();
当ServerChannel没用关闭前,会一直阻塞在这里,这样可以防止主线程执行结束
private void doClose0(ChannelPromise promise) {
try {
doClose();
closeFuture.setClosed();
safeSetSuccess(promise);
} catch (Throwable t) {
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
关闭serverchannel之后,这里会放开阻塞
ChannelHandlerContext与Channel
出栈方法
read,write,connect,close等 以writeA为例,比较区别 ChannelHandlerContext调用
private void write(Object msg, boolean flush, ChannelPromise promise) {
AbstractChannelHandlerContext next = findContextOutbound();
final Object m = pipeline.touch(msg, next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
if (flush) {
next.invokeWriteAndFlush(m, promise);
} else {
next.invokeWrite(m, promise);
}
} else {
AbstractWriteTask task;
if (flush) {
task = WriteAndFlushTask.newInstance(next, m, promise);
} else {
task = WriteTask.newInstance(next, m, promise);
}
safeExecute(executor, task, promise, m);
}
}
channel调用
@Override
public ChannelFuture writeAndFlush(Object msg) {
return pipeline.writeAndFlush(msg);
}
@Override
public final ChannelFuture writeAndFlush(Object msg) {
return tail.writeAndFlush(msg);
}
可见,调用出栈方法,channel时从头调用,而ChannelHandlerContext是从本身找到下一个继续执行。
注意,如果我们实现出栈handler,在处理完毕之后一定记得 ctx.write,链式执行下一个handler,否则,无法执行到HeadContext中的write是无法把消息真正发出去的。
入栈方法
入栈方法channel并不能调用 ChannelHandlerContext调用read
@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
invokeChannelRead(findContextInbound(), msg);
return this;
}
private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound);
return ctx;
}
可以看出来, ChannelHandlerContext调用入栈方法都是fire开头,执行链表下一个入栈方法