Netty入门-组件Channel
3.2、Channel
- close() 关闭channel
- closeFuture() 用来处理channel的关闭
- sync() 同步等待channel关闭
- addListener() 异步等待channel关闭
- pipeline() 添加处理器
- write() 将数据写入缓冲区,但不会立即输出
- wrireAndFlush() 写入并刷出
channelfuture详解
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
//1. 启动类
ChannelFuture channelFuture = new Bootstrap()
//2. 添加EventLoop
.group(new NioEventLoopGroup())
//3. 选择客户端channel实现
.channel(NioSocketChannel.class)
//4. 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
//在连接建立后被调用
protected void initChannel(NioSocketChannel channel) throws Exception {
//编码器,将要发送的消息转为ByteBuf
channel.pipeline().addLast(new StringEncoder());
}
})
//5. 连接到服务器
.connect(new InetSocketAddress(8080));
//阻塞方法,知道连接建立
channelFuture.sync();
//代表连接对象
Channel channel = channelFuture.channel();
//6. 向服务端发送数据
channel.writeAndFlush("hello server");
}
}
-
处理方式1:sync方法同步阻塞等待建立连接 需
//处理方式1:sync同步阻塞,等待建立连接 Channel channel = channelFuture //阻塞方法,直到连接建立 .sync() //代表连接对象 .channel(); channel.writeAndFlush("sync-msg..."); System.out.println(channel); System.out.println("=====");
sync()方法作用。
如果没有sync,因为connect方法是异步非阻塞的,由main发起调用,真正执行connnect的是nio线程,连接是需要时间的,可能连接还没有建立成功,就去调用channel,显然此时是没有channel的,发送数据的方法是有channel调用的,肯定是发送不了的
-
处理方式2:异步处理,由其他线程处理
//2.处理方式2:通过addListener异步处理 channelFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { channelFuture.channel(); channel.writeAndFlush("async-msg..."); } });
closeFuture谅解
@Slf4j
public class CloseFutureClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup();
//1. 启动类
ChannelFuture channelFuture = new Bootstrap()
//2. 添加EventLoop
.group(new NioEventLoopGroup())
//3. 选择客户端channel实现
.channel(NioSocketChannel.class)
//4. 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
//在连接建立后被调用
protected void initChannel(NioSocketChannel channel) throws Exception {
//编码器,将要发送的消息转为ByteBuf
channel.pipeline().addLast(new StringEncoder());
}
})
//5. 连接到服务器
.connect(new InetSocketAddress(8080));
//处理方式1:sync同步阻塞,等待建立连接
Channel channel = channelFuture
//阻塞方法,直到连接建立
.sync()
//代表连接对象
.channel();
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
while (true) {
String s = scanner.nextLine();
if ("q".equals(s)) {
//close是异步的,是由nio线程执行的
channel.close();
//关闭之后的其他操作,但是不能在这里善后处理,因为close方法异步的,有可能close还没执行,就走到了关闭之后的操作
//解决:使用closeFuture来处理,方式1:同步 方式2:异步
//log.info("关闭之后的操作");
break;
}
channel.writeAndFlush(s);
}
}, "input").start();
ChannelFuture closeFuture = channel.closeFuture();
//方式1:同步,是在main线程中处理
/*closeFuture.sync();
//关闭之后的操作
log.info("同步关闭之后的操作");
group.shutdownGracefully();*///优雅关闭客户端,停止java
//方式2:异步,是在nio线程里处理
closeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
log.info("异步关闭之后的操作");
group.shutdownGracefully();//优雅关闭客户端,停止java
}
});
}
}
观察结果:
//方式1,看到是main
08:46:52.171 [main] INFO com.jpy.netty.c2.CloseFutureClient - 同步关闭之后的操作
//方式1看到思nio
08:53:35.956 [nioEventLoopGroup-2-1] INFO com.jpy.netty.c2.CloseFutureClient - 异步关闭之后的操作
注意点:
- close方法是在nio线程中执行的,所以不能在close调用后直接进行善后处理,这样善后处理是在new Thread里执行,两个线程无法保障顺序
- 方式1:同步,善后处理是在main中执行
- 方式2:异步,善后处理是在nio线程中
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY