0%

java | Netty 简介

因为公司用 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 {
// 服务器端的启动器
// 组装 netty 组件
new ServerBootstrap()
.group(new NioEventLoopGroup())
// 选择服务器的实现 NIO/BIO
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
// 将 bytebuff 转化为字符
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
    • 数据处理工序
      • 工序分为 InboundOurbound
      • 工序有很多道,合在一起就是 pipeline「一个 pipeline 相当于责任链」,pipeline 负责发布事件「读、读取完成」传递给每一个 handlerhandler 对自己感兴趣的事件进行处理
  • eventloop
    • 处理数据的工人
      • 工人可以管理多个 channelio 操作,并且一个工人一旦负责某一个 channel 就要负责到底
      • 工人既可以执行 IO 也可以并行执行任务处理,每一个工人都有任务队列,队列里可以放多个 channel 待处理任务,任务分为普通任务和定时任务
      • 工人按照 pipeline 顺序,依次按照 handler 的规划处理数据,为每道工序指定不同的工人
请我喝杯咖啡吧~