因为公司用 netty
来创建 socket
的客户端和服务端。
参考资料
版本说明
- Netty 3.x : 版本太老 , 不推荐使用 ;
- Netty 4.x : 目前正在使用的版本 ( 必须使用这个版本 ) , 目前最新的是 netty-4.1.50 版本 ( 2020-05-13 ) ;
- Netty 5.x : 由于出现重大 BUG , 已经废弃 , 不能使用 ;
代码
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.redisc;
import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringEncoder;
import java.io.IOException; import java.net.InetSocketAddress;
public class Client { public static void main(String[] args) throws IOException, InterruptedException { new Bootstrap() .group(new NioEventLoopGroup()) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<NioSocketChannel>() { @Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { nioSocketChannel.pipeline().addLast(new StringEncoder());
} }).connect(new InetSocketAddress("localhost", 8877)) .sync().channel().writeAndFlush("hello"); } }
|
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.redisc;
import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder;
import java.io.IOException;
public class Run {
public static void main(String[] args) throws IOException { new ServerBootstrap() .group(new NioEventLoopGroup()) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<NioSocketChannel>() { @Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { nioSocketChannel.pipeline().addLast(new StringDecoder()); nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println(msg); } }); } }).bind(8877); }
}
|
执行流程
正确理解
channel
msg
- 在
channel
中流动的数据,最开始的时候是 Bytebuf
但是经过 pipeline
加工后转为其它变量,最后输出又变成了 ByteBuf
handler
- 数据处理工序
- 工序分为
Inbound
和 Ourbound
- 工序有很多道,合在一起就是
pipeline
「一个 pipeline 相当于责任链」,pipeline
负责发布事件「读、读取完成」传递给每一个 handler
,handler
对自己感兴趣的事件进行处理
eventloop
- 处理数据的工人
- 工人可以管理多个
channel
的 io
操作,并且一个工人一旦负责某一个 channel
就要负责到底
- 工人既可以执行
IO
也可以并行执行任务处理,每一个工人都有任务队列,队列里可以放多个 channel
待处理任务,任务分为普通任务和定时任务
- 工人按照
pipeline
顺序,依次按照 handler
的规划处理数据,为每道工序指定不同的工人