channel的主要作用
HelloServer 服务端
@Slf4j(topic = "w.Test1")
public class HelloServer {
public static void main(String[] args) {
// 创建启动器
new ServerBootstrap()
// 创建EventLoop事件监听处理组
.group(new NioEventLoopGroup())
// 设置ServerSocketChannel的实现NioServerSocketChannel
.channel(NioServerSocketChannel.class)
// 设置处理器
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
// 添加处理工序 处理stringBuf为字符串
ch.pipeline().addLast(new StringDecoder());
// 自定义处理器
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
// 监听读时间
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 打印上一步转换好的字符串
log.debug((String) msg);
}
});
}
}).bind(8080); // 绑定的监听端口
}
}
HelloClient 客户端
@Slf4j(topic = "w.Test1")
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
//1 启动类
new Bootstrap()
// 2.添加EventLoop
.group(new NioEventLoopGroup())
// 3.选择客服端channel实现
.channel(NioSocketChannel.class)
// 4 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
// 连接地址
}).connect(new InetSocketAddress("127.0.0.1", 8080))
.sync()
.channel()
.write("hello world");
}
}
都运行起来发现服务端并没有收到发送的"hello world"
write方法本身是吧数据写入缓存去区中去了,并没有刷出,修改方法为writeAndFlush()
发现服务端正确的收到了发送的数据
把上面代码的sync去掉,再重新跑起来发现没有办法服务端没有办法正确接收信息了
发送的"hello world"并没有正确打印,这是因为建立连接和发送数据并不是一个线程,他们异步了,主线程不会等待工作线程的连接建立,当工作线程开始去建立连接时,main线程都已经把数据都发了,这时main线程就相当于发了个寂寞
而用sync()会一直阻塞到连接的建立这时再去发送数据就没得问题了
addListener添加一个回调方法在回调方法里面执行发送数据也是没有问题的
@Slf4j
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
//1 启动类
ChannelFuture connect = new Bootstrap()
// 2.添加EventLoop
.group(new NioEventLoopGroup())
// 3.选择客服端channel实现
.channel(NioSocketChannel.class)
// 4 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
// 连接地址
}).connect(new InetSocketAddress("127.0.0.1", 8080));
// .sync()
// .channel()
// .writeAndFlush("hello world");
connect.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
Channel channel = channelFuture.channel();
log.debug("连接完成{}", channel);
channel.writeAndFlush("hello world");
}
});
}
}
相当于我们给了一个回调函数,当工作线程建立连接后,在由它来调用operationComplete方法来执行发送
同步
@Slf4j
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup();
//1 启动类
ChannelFuture connect = new Bootstrap()
// 2.添加EventLoop
.group(group)
// 3.选择客服端channel实现
.channel(NioSocketChannel.class)
// 4 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
// 连接地址
}).connect(new InetSocketAddress("127.0.0.1", 8080))
// 同步关闭客户端
.sync()
.channel()
.writeAndFlush("hello world") // 发送数据
.sync() // 等待数据发送完毕
.channel() // 拿到channel
.close()// 关闭他
.channel()// 拿到channel
.closeFuture()// 拿到closeFuture
.sync(); // 等待关闭
log.debug("关闭客户端");
// 关闭线程组
group.shutdownGracefully();
}
}
异步关闭
@Slf4j
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup();
//1 启动类
ChannelFuture connect = new Bootstrap()
// 2.添加EventLoop
.group(group)
// 3.选择客服端channel实现
.channel(NioSocketChannel.class)
// 4 添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
// 连接地址
}).connect(new InetSocketAddress("127.0.0.1", 8080))
// 同步关闭客户端
.sync()
.channel()
.writeAndFlush("hello world") // 发送数据
.sync() // 等待数据发送完毕
.channel() // 拿到channel
.close()// 关闭他
.channel()// 拿到channel
.closeFuture();
connect.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
log.debug("关闭客户端");
// 关闭线程组
group.shutdownGracefully();
}
});
}
}