项目路径:

E:\_1\java\project\java-project-learning\java-study\netty-std

git地址:

https://gitee.com/wei-yuliu/java-project-learning

代码

EventLoopGroup bossGroup = new NioEventLoopGroup(1); //负责接收连接一个线程就能处理
// workerGroup:负责处理已建立连接的读写,线程数默认:cpu核心*2
EventLoopGroup workerGroup = new NioEventLoopGroup();

ServerBootstrap bootstrap = new ServerBootstrap();//理解为服务器装配器
bootstrap.group(bossGroup, workerGroup)
    .channel(NioServerSocketChannel.class)//基于Java NIO实现的服务器Channel
    .option(ChannelOption.SO_BACKLOG, 128)       // 等待连接的队列大小
    .childOption(ChannelOption.SO_KEEPALIVE, true) // 保持长连接
    .childHandler(new ChannelInitializer<SocketChannel>() {
    	@Override
    	protected void initChannel(SocketChannel ch) {
        	ch.pipeline().addLast(new EchoServerHandler());
    	}
	});

class EchoServerHandler extends io.netty.channel.ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(io.netty.channel.ChannelHandlerContext ctx, Object msg) {
        String message = (String) msg;
        System.out.println("[服务端] 收到客户端消息: " + message);
        // 原样发回给客户端(回声)
        ctx.writeAndFlush("ECHO: " + message);
    }
}

ChannelFuture future = bootstrap.bind(8080).sync();
future.channel().closeFuture().sync();
Channel 分成两种,和NIO类似
NioServerSocketChannel//代表整个监听端口,例如:0.0.0.0:8080
NioSocketChannel//客户端的信息,ip和端口
option 和 childOption,配置Socket参数
  • ChannelOption.SO_BACKLO:表示操作系统等待服务器接受连接的队列容量。

  • ChannelOption.SO_KEEPALIVE:开启TCP KeepAlive。长连接。

option       → NioServerSocketChannel
childOption  → NioSocketChannel
初始化每条连接的Pipeline

childHandler: 每来一个新连接,都会执行一次 initChannel,创建处理对象,每个连接都有自己的pipeline。

这里SocketChannel是接口,按道理应该写成NioSocketChannel,但是后面如果Linux环境换成:EpollSocketChannel

.childHandler(new ChannelInitializer<SocketChannel>() {
    @Override
    protected void initChannel(SocketChannel ch) {
        ch.pipeline().addLast(new EchoServerHandler());
    }
});
向操作系统申请绑定8080端口。

异步操作,立即返回,所以要改成同步sync()

ChannelFuture future = bootstrap.bind(8080).sync();

等待服务器 socket 关闭

future.channel().closeFuture().sync();

future.channel()拿到的是服务器Channel:NioServerSocketChannel

closeFuture()还是异步的,改成同步sync()。一般除非主动关,不然不会执行这个。

完成Lesson 1后:

  1. Boss负责接受连接,Worker负责连接读写。
  2. ServerBootstrap负责装配服务器。
  3. NioServerSocketChannel代表监听端口。
  4. 每个客户端连接拥有自己的Channel和Pipeline。
  5. Inbound数据从Pipeline前向后传播。
  6. Outbound数据从Pipeline后向前传播。
  7. Decoder将字节转换成业务对象。
  8. Encoder将业务对象转换成字节。
  9. bind()是异步操作,sync()负责等待结果。
  10. closeFuture().sync()让服务器持续运行。
  11. shutdownGracefully()负责释放Netty线程资源。