Netty | 03 - 客户端与服务端双向通信
发布日期:2022-02-21 17:40:28
浏览次数:58
分类:技术文章
本文共 3209 字,大约阅读时间需要 10 分钟。
1 客户端数据读取
客户端相关的数据读写逻辑是通过 Bootstrap 的 handler()
方法指定
.handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { // 指定连接数据读写逻辑 // 返回的是和这条连接相关的逻辑处理链,采用了责任链模式 // 然后再调用 addLast() 方法 添加一个逻辑处理器 // 这个逻辑处理器为的就是在客户端建立连接成功之后,向服务端写数据 ch.pipeline().addLast(new FirstClientHandler()); }});
下面看下FirstClientHandler
的实现
public class FirstClientHandler extends ChannelInboundHandlerAdapter { // channelActive()方法会在客户端连接建立成功之后被调用 @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 = "hello word".getBytes(Charset.forName("utf-8")); // 3. 填充数据到 ByteBuf buffer.writeBytes(bytes); return buffer; }}
内存管理器的作用就是分配一个 ByteBuf,然后把字符串的二进制数据填充到 ByteBuf,这样就获取到了 Netty 需要的数据格式,最后调用 ctx.channel().writeAndFlush()
把数据写到服务端
2 服务端读取客户端数据
服务端相关的数据处理逻辑是通过 ServerBootstrap 的 childHandler()
方法指定
.childHandler(new ChannelInitializer() { protected void initChannel(NioSocketChannel ch) { // 指定连接数据读写逻辑 // 添加一个逻辑处理器 ch.pipeline().addLast(new FirstServerHandler()); }});
下面看下FirstClientHandler
的实现
public class FirstServerHandler extends ChannelInboundHandlerAdapter { // 方法在接收到客户端发来的数据之后被回调 @Override public void channelRead(ChannelHandlerContext ctx , Object msg // msg 参数指的就是 Netty 里面数据读写的载体 ) { ByteBuf byteBuf = (ByteBuf) msg; System.out.println(new Date() + ": 服务端读到数据 -> " + byteBuf.toString(Charset.forName("utf-8"))); }}
先运行服务端,再运行客户端,便可以接收到消息。
3 服务端返回数据给客户端
服务端向客户端写数据逻辑与客户端侧的写数据逻辑一样:
- 先创建一个 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 = "你好,欢迎关注我的微信公众号,《闪电侠的博客》!".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"))); }}
4 小结
- 客户端和服务端的逻辑处理是均是在启动的时候给逻辑处理链 pipeline 添加逻辑处理器,来编写数据的读写逻辑;
- 客户端连接成功之后会回调到逻辑处器的 channelActive() 方法,而不管是服务端还是客户端,收到数据之后都会调用到 channelRead 方法;
- 写数据调用
writeAndFlush()
方法,客户端与服务端交互的二进制数据载体为 ByteBuf- ByteBuf 通过连接的内存管理器创建
- 字节数据填充到 ByteBuf 之后才能写到对端;
转载地址:https://blog.csdn.net/weixin_40597409/article/details/122904011 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月01日 18时25分23秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Android的.dex、.odex与.oat文件扫盲
2019-04-27
Unity移动应用如何在Bugly上查看崩溃堆栈
2019-04-27
unity3D 在屏幕边框创建碰撞框
2019-04-27
xml中常用的转义符
2019-04-27
关于MSDK的几个难点
2019-04-27
使用UnityEditor做工具
2019-04-27
Visual Studio我常用的快捷键
2019-04-27
写C# dll供Unity调用
2019-04-27
Linux制作run安装包
2019-04-27
一分钟学会C#解析XML
2019-04-27
unity AssetBundle的资源管理
2019-04-27
【转】Unity中HideInInspector和SerializeField一起使用
2019-04-27
单例模板类
2019-04-27
Unity与java相互调用
2019-04-27
android截屏代码
2019-04-27
unity NGUI图文混排
2019-04-27
Unity项目优化
2019-04-27
Unity3D Shader 入门
2019-04-27
MSDK手Q邀请透传参数问题:url编解码与base64编解码
2019-04-27