博主分享免费Java教学视频,B站账号:Java刘哥
在前面两个小节,我们已经学习了服务端启动与客户端启动的流程,熟悉了这两个过程之后,就可以建立服务端与客户端之间的通信了,本小节,我们用一个非常简单的 Demo 来了解一下服务端和客户端是如何来通信的。
现在,我们在
现在,我们在
这个方法里面的逻辑和客户端侧类似,获取服务端侧关于这条连接的逻辑处理链
服务端侧的逻辑处理器同样继承自
服务端
到目前为止,我们已经实现了客户端发数据服务端打印,离我们本小节开始的目标还差一半,接下来的部分我们来实现另外一半:服务端收到数据之后向客户端回复数据
现在,轮到客户端了。客户端的读取数据的逻辑和服务端读取数据的逻辑一样,同样是覆盖
将这段逻辑添加到客户端之后逻辑处理器
服务端
文章转自闪电侠的《 Netty入门与实战》
本小节,我们要实现的功能是:客户端连接成功之后,向服务端写一段数据 ,服务端收到数据之后打印,并向客户端回一段数据,文章里面展示的是核心代码,完整代码请参考 GitHub
一、客户端发数据到服务端
在客户端启动流程这一小节,我们提到, 客户端相关的数据读写逻辑是通过Bootstrap
的 handler()
方法指定
- .handler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) {
- // 指定连接数据读写逻辑
- }
- });
initChannel()
方法里面给客户端添加一个逻辑处理器,这个处理器的作用就是负责向服务端写数据
- .handler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) {
- ch.pipeline().addLast(new FirstClientHandler());
- }
- });
ch.pipeline()
返回的是和这条连接相关的逻辑处理链,采用了责任链模式,这里不理解没关系,后面会讲到- 然后再调用
addLast()
方法 添加一个逻辑处理器,这个逻辑处理器为的就是在客户端建立连接成功之后,向服务端写数据,下面是这个逻辑处理器相关的代码
- public class FirstClientHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelActive(ChannelHandlerContext ctx) {
- System.out.println(new Date() + ": 客户端写出数据");
- // 1. 获取数据
- ByteBuf buffer = getByteBuf(ctx);
- // 2. 写数据
- ctx.channel().writeAndFlush(buffer);
- }
- private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
- // 1. 获取二进制抽象 ByteBuf
- ByteBuf buffer = ctx.alloc().buffer();
- // 2. 准备数据,指定字符串的字符集为 utf-8
- byte[] bytes = "你好,Netty!".getBytes(Charset.forName("utf-8"));
- // 3. 填充数据到 ByteBuf
- buffer.writeBytes(bytes);
- return buffer;
- }
- }
- 这个逻辑处理器继承自
ChannelInboundHandlerAdapter
,然后覆盖了channelActive()
方法,这个方法会在客户端连接建立成功之后被调用 - 客户端连接建立成功之后,调用到
channelActive()
方法,在这个方法里面,我们编写向服务端写数据的逻辑 - 写数据的逻辑分为两步:首先我们需要获取一个 netty 对二进制数据的抽象
ByteBuf
,上面代码中,ctx.alloc()
获取到一个ByteBuf
的内存管理器,这个 内存管理器的作用就是分配一个ByteBuf
,然后我们把字符串的二进制数据填充到ByteBuf
,这样我们就获取到了 Netty 需要的一个数据格式,最后我们调用ctx.channel().writeAndFlush()
把数据写到服务端
二、服务端读取客户端数据
在服务端端启动流程这一小节,我们提到, 服务端相关的数据处理逻辑是通过ServerBootstrap
的 childHandler()
方法指定
- .childHandler(new ChannelInitializer<NioSocketChannel>() {
- protected void initChannel(NioSocketChannel ch) {
- // 指定连接数据读写逻辑
- }
- });
initChannel()
方法里面给服务端添加一个逻辑处理器,这个处理器的作用就是负责读取客户端来的数据
- .childHandler(new ChannelInitializer<NioSocketChannel>() {
- protected void initChannel(NioSocketChannel ch) {
- ch.pipeline().addLast(new FirstServerHandler());
- }
- });
pipeline
,然后添加一个逻辑处理器,负责读取客户端发来的数据
- public class FirstServerHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- ByteBuf byteBuf = (ByteBuf) msg;
- System.out.println(new Date() + ": 服务端读到数据 -> " + byteBuf.toString(Charset.forName("utf-8")));
- }
- }
ChannelInboundHandlerAdapter
,与客户端不同的是,这里覆盖的方法是 channelRead()
,这个方法在接收到客户端发来的数据之后被回调。
这里的 msg
参数指的就是 Netty 里面数据读写的载体,为什么这里不直接是 ByteBuf
,而需要我们强转一下,我们后面会分析到。这里我们强转之后,然后调用 byteBuf.toString()
就能够拿到我们客户端发过来的字符串数据。
我们先运行服务端,再运行客户端,下面分别是服务端控制台和客户端控制台的输出
客户端


三、服务端回数据给客户端
服务端向客户端写数据逻辑与客户端侧的写数据逻辑一样,先创建一个ByteBuf
,然后填充二进制数据,最后调用 writeAndFlush()
方法写出去,下面是服务端回数据的代码
- public class FirstServerHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- // ... 收数据逻辑省略
- // 回复数据到客户端
- System.out.println(new Date() + ": 服务端写出数据");
- ByteBuf out = getByteBuf(ctx);
- ctx.channel().writeAndFlush(out);
- }
- private ByteBuf getByteBuf(ChannelHandlerContext ctx) {
- byte[] bytes = "你好,我是Netty,很高兴能遇到你!".getBytes(Charset.forName("utf-8"));
- ByteBuf buffer = ctx.alloc().buffer();
- buffer.writeBytes(bytes);
- return buffer;
- }
- }
ChannelRead()
方法
- public class FirstClientHandler extends ChannelInboundHandlerAdapter {
- // 写数据相关的逻辑省略
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- ByteBuf byteBuf = (ByteBuf) msg;
- System.out.println(new Date() + ": 客户端读到数据 -> " + byteBuf.toString(Charset.forName("utf-8")));
- }
- }
FirstClientHandler
之后,客户端就能收到服务端发来的数据,完整的代码参考 GitHub
客户端与服务端的读写数据的逻辑完成之后,我们先运行服务端,再运行客户端,控制台输出如下
客户端


- 微信
- 交流学习,有偿服务
-
- 博客/Java交流群
- 资源分享,问题解决,技术交流。群号:590480292
-
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏