1. 从一个简单的CS demo说起
1. 从一个简单的CS demo说起
从一个简单的CS demo说起
CS模式源码
接下来提供用于演示Netty的源码
- 服务端
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
public class NettyServer { public static void main(String[] args) { ServerBootstrap serverBootstrap = new ServerBootstrap(); try (EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup()) { serverBootstrap .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .option(ChannelOption.SO_REUSEADDR, true) .handler(new LoggingHandler(LogLevel.INFO)) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_RCVBUF, 64 * 1024) .childOption(ChannelOption.SO_SNDBUF, 64 * 1024) .childHandler(new ChannelInitializer() { @Override protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new NettyServerHandler()); } }); ChannelFuture channelFuture = serverBootstrap.bind(10009).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
public class NettyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf byteBuf = (ByteBuf) msg; byte[] body = new byte[byteBuf.readableBytes()]; byteBuf.readBytes(body); System.out.println(new String(body)); byte[] responseBytes = "hi,客户端,我是服务端".getBytes(); ctx.channel().writeAndFlush(Unpooled.wrappedBuffer(responseBytes)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); } }
服务端执行流程详解
初始化ServerBootstrap:
ServerBootstrap 是 Netty 提供的一个辅助类,用于简化服务器端的启动过程。通过它可以设置服务器的各种参数和选项。
创建两个事件循环组(EventLoopGroup):
- bossGroup:负责处理客户端的连接请求。通常只需要一个线程。
- workerGroup:负责处理 I/O 操作,如读写数据。可以根据需要配置多个线程。
配置服务器选项:
- SO_BACKLOG:指定了内核为此套接口排队的最大连接个数。
- SO_REUSEADDR:允许重用本地地址和端口。
配置子通道选项:
- TCP_NODELAY:禁用 Nagle 算法,减少延迟。
- SO_RCVBUF 和 SO_SNDBUF:设置接收和发送缓冲区的大小。
添加管道处理器:
通过 ChannelPipeline 添加自定义的 NettyServerHandler,用于处理业务逻辑。ChannelPipeline 是一个处理器链,所有的 I/O 事件都会在这个链上传递。
绑定端口并启动服务器:
服务器绑定到端口 10009,开始监听客户端连接。bind 方法返回一个 ChannelFuture 对象,通过调用 sync 方法等待绑定操作完成。
关闭服务器: 主线程等待,直到服务器关闭。通过调用 closeFuture().sync() 方法,确保服务器在关闭前不会退出。
客户端
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
public class NettyClient { public static void main(String[] args) { Bootstrap bootstrap = new Bootstrap(); try (EventLoopGroup bossGroup = new NioEventLoopGroup()) { bootstrap .group(bossGroup) .channel(NioSocketChannel.class) .option(ChannelOption.SO_RCVBUF, 64 * 1024) .option(ChannelOption.SO_SNDBUF, 64 * 1024) .option(ChannelOption.SO_REUSEADDR, true) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new NettyClientHandler()); } }); ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 10009).sync(); channelFuture.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
public class NettyClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { byte[] bytes = "hi,服务端,我是客户端!".getBytes(); ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); ctx.channel().writeAndFlush(byteBuf); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf responseByteBuf = (ByteBuf) msg; byte[] responseByte = new byte[responseByteBuf.readableBytes()]; responseByteBuf.readBytes(responseByte); System.out.println(new String(responseByte)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); } }
客户端执行流程详解
- 初始化Bootstrap:
- 创建事件循环组(EventLoopGroup) EventLoopGroup 负责处理所有的 I/O 事件。客户端通常只需要一个事件循环组。
- 配置客户端选项:
- 添加管道处理器:
- 连接服务器:
- 关闭连接:
本文由作者按照 CC BY 4.0 进行授权