【netty】Channel

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();
            }
        });
    }

}
相关推荐
拉不动的猪7 小时前
移动端调试工具VConsole初始化时的加载阻塞问题
前端·javascript·微信小程序
大金乄10 小时前
封装一个vue2的elementUI 表格组件(包含表格编辑以及多级表头)
前端·javascript
Lee川12 小时前
解锁 JavaScript 的灵魂:深入浅出原型与原型链
javascript·面试
swipe12 小时前
从原理到手写:彻底吃透 call / apply / bind 与 arguments 的底层逻辑
前端·javascript·面试
Lee川14 小时前
探索JavaScript的秘密令牌:独一无二的`Symbol`数据类型
javascript·面试
Lee川14 小时前
深入浅出JavaScript事件机制:从捕获冒泡到事件委托
前端·javascript
光影少年14 小时前
async/await和Promise的区别?
前端·javascript·掘金·金石计划
codingWhat15 小时前
如何实现一个「万能」的通用打印组件?
前端·javascript·vue.js
前端Hardy17 小时前
别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
前端·javascript·vue.js
前端Hardy17 小时前
别再让 `console.log` 上线了!它正在悄悄拖垮你的生产系统
前端·javascript·vue.js