channel 的主要作用
• close() 可以用来关闭 channel
• closeFuture() 用来处理 channel 的关闭
sync 方法作用是同步等待 channel 关闭
而 addListener 方法是异步等待 channel 关闭
• pipeline() 方法添加处理器
• write() 方法将数据写入
• writeAndFlush() 方法将数据写入并刷出
ChannelFuture.sync()
阻塞住当前线程,知道建立链接的nio线程建立链接之后,才会继续往下进行。
ChannelFuture.connect的方法是异步非阻塞的方法,所以在连接的服务器的时候,会单独的用零一个nio线程去做connect操作(或许预计1s的时间),但是此时mian线程会继续往下执行代码。向服务器发送数据信息。
java
Bootstrap bootstrap = new Bootstrap();
ChannelFuture channelFuture = bootstrap.group(new NioEventLoopGroup())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
})
.connect(new InetSocketAddress("localhost", 8081));
channelFuture.sync();
Channel channel = channelFuture.channel();
channel.writeAndFlush("hello").channel();
System.out.println(channel);
如果没有调用sync方法,则server会接受不到client的消息。从打印channel的信息状态来看,我们也是之后channel的信息,没有链接服务器的信息,这里做个对比。
bash
Connected to the target VM, address: '127.0.0.1:53547', transport: 'socket'
[id: 0x31ab0c71]
bash
Connected to the target VM, address: '127.0.0.1:54059', transport: 'socket'
[id: 0x151e03d2, L:/127.0.0.1:54062 - R:localhost/127.0.0.1:8081]
ChannelFuture.addListener回调对象
异步处理结果
在nio线程建立链接之后,会调用operationComplete方法
sync是等建立链接的nio线程来建立之后,主线程发送并等待结果
addListener是开启了一个新的线程,发送并等待结果
java
Bootstrap bootstrap = new Bootstrap();
ChannelFuture channelFuture = bootstrap.group(new NioEventLoopGroup())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
})
.connect(new InetSocketAddress("localhost", 8081));
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
Channel channel = channelFuture.channel();
log.info("{}", channel);
channel.writeAndFlush("heloo");
}
});
}
ClosedFuture
channel.close();也是异步操作,单独开启一个线程去进行关闭操作
这就导致了,我们紧随其后的在close之后进行一些善后处理工作,可能会在真正close的线程之前就开始操作了。
如果我们想在close之后去进行一些操作,例如善后处理的动作,那么就需要closedFuture
同步操作sync
java
@Slf4j
public class TestChannelFutureClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
ChannelFuture channelFuture = bootstrap.group(nioEventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
})
.connect(new InetSocketAddress("localhost", 8081));
Channel channel = channelFuture.sync().channel();
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
while (true) {
String s = scanner.nextLine();
if ("q".equals(s)) {
channel.close();
break;
}
channel.writeAndFlush(s);
}
}).start();
ChannelFuture closeFuture = channel.closeFuture();
closeFuture.sync();
log.info("在channel关闭之后,才执行");
}
}
异步操作addListener
java
package org.example.netty_study.channelFuture;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.util.Scanner;
@Slf4j
public class TestChannelFutureClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
ChannelFuture channelFuture = bootstrap.group(nioEventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
})
.connect(new InetSocketAddress("localhost", 8081));
Channel channel = channelFuture.sync().channel();
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
while (true) {
String s = scanner.nextLine();
if ("q".equals(s)) {
channel.close();
break;
}
channel.writeAndFlush(s);
}
}).start();
ChannelFuture closeFuture = channel.closeFuture();
closeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
log.info("在channel关闭之后,才执行");
nioEventLoopGroup.shutdownGracefully();
}
});
}
}