文章目录
  • 一、前言
  • 二、整体运行:先启动服务端,然后启动客户端,发送三条消息
  • 三、客户端和服务端
  • 3.1 客户端(重要)
  • 3.2 服务端(重要)
  • 3.3 编码和解码(了解即可)
  • 四、尾声


一、前言

源码下载: https://www.syjshare.com/res/XEE10LTG

二、整体运行:先启动服务端,然后启动客户端,发送三条消息

先启动server

Netty_04_消息协议设计与实战(实践类)_网络

启动客户端,发送三条消息

Netty_04_消息协议设计与实战(实践类)_java_02

对于三条消息时,都是client发送,server接收,而且是 channel. 发送的,不是 outBound 发送的,所以 clientHandler 和 serverHandler 都是继承 inBound ,只有 channelRead 方法,用来接收消息

服务端日志

Netty_04_消息协议设计与实战(实践类)_客户端_03

服务收到的消息 reqType 是 0 ,表示 request 请求

客户端日志

Netty_04_消息协议设计与实战(实践类)_java_04

步骤1:启动服务端
步骤2:启动客户端,向服务端发送三条消息
步骤3:服务端的ServerHandler channelRead方法收到消息,并立马在 channelRead 方法里面,向客户端发送一条 reqType 是 1 ,表示 Resp 消息,收到三条来自客户端的消息,就向客户端发送三条响应
步骤4:客户端的ClientHandler channelRead方法收到来自服务端的三条响应,直接在自己的console打印了出来

无论是服务端还是客户端,都是 pipeline.addLast 加上了 MessageRecordDecode 和 MessageRecordEncode 两个类,

客户端:MessageRecordEncode

三、客户端和服务端

3.1 客户端(重要)

客户端:

步骤1:拼装MessageRecord对象

步骤2:pipeline中addLast添加了 MessageRecordEncode,会接受即将发送的 MessageRecord 对象,消息头直接 ByteBuf out 发送出去,消息体序列化为byte[]数组(此处使用Java IO ByteArrayOutputStream流),然后 ByteBuf out 发送出去

步骤3:收到服务端的响应,因为 pipeline 中 addLast 添加了 MessageRecordDecode ,会使用 ByteBuf in 接受收到的 byte[] 数组流,然后在 decode 函数中,拼装成 MessageRecord 对象,对象头就直接取出来就好,对象体需要通过 Java IO ByteArrayInputStream 读进来,反序列化为对象

步骤4:client 收到了 decode 反序列的对象:clientHandler仅仅是继承ChannelInboundHandlerAdapter接收消息,inbound,在 console 打印一下

具体如下:

Netty_04_消息协议设计与实战(实践类)_服务端_05


Netty_04_消息协议设计与实战(实践类)_网络_06


Netty_04_消息协议设计与实战(实践类)_网络_07

Netty_04_消息协议设计与实战(实践类)_服务端_08

最后看一下日志:

步骤1:拼装 MessageRecord 没有日志
步骤2:编码有一个日志 log.info("==========开始进行消息编码=================="); 步骤3:解码有一个日志 log.info("反序列化出来的结果:"+record); 步骤4:打印消息有一个日志 log.info("ent Receive Message:"+record);

Netty_04_消息协议设计与实战(实践类)_java_09

Netty_04_消息协议设计与实战(实践类)_java_10

最后回顾一下 client pipeline addLast 四个handler

Netty_04_消息协议设计与实战(实践类)_客户端_11

header 直接 getXxx setXxx ,body 需要ByteArrayInputStream读进来,反序列化为对象,ByteArrayOutputStream写出去,序列化为byte[]
ByteArrayOutputStream 写出去,对象序列化为byte[],ByteArrayInputStream 读进来,byte[]反序列化为对象

3.2 服务端(重要)

服务端:
步骤1:收到消息,MessageRecordDecode 类起作用,byte[]数组反序列化为对象bean
步骤2: serverHandler channelRead 消息打印一下
步骤3:发送消息 serverHandler channelRead 里面
步骤4:msg bean不能直接发送,发送前需要编码

具体如下:

Netty_04_消息协议设计与实战(实践类)_客户端_12


Netty_04_消息协议设计与实战(实践类)_开发语言_13

Netty_04_消息协议设计与实战(实践类)_客户端_14


Netty_04_消息协议设计与实战(实践类)_java_15

最后看一下日志:

步骤1:解码有一个日志 log.info("反序列化出来的结果:"+record); 步骤2:进入 ServerHandler 有一个日志 log.info("Server Receive Message:"+record);,然后拼装 MessageRecord

步骤3:ServerHandler channelRead 发送没有日志

步骤4:编码有一个日志 log.info("==========开始进行消息编码==================");

Netty_04_消息协议设计与实战(实践类)_网络_16

Netty_04_消息协议设计与实战(实践类)_客户端_17

最后回顾一下 server pipeline addLast 四个handler

Netty_04_消息协议设计与实战(实践类)_服务端_18

3.3 编码和解码(了解即可)

编码,写出去,对象 变为 二进制流/byte[]数组
编码的目的是要写出去,通过 ObjectOutputStream 写出去,所以要将 对象 变为 二进制流/byte[]数组 ,然后传输到网络上去

protected void encode(ChannelHandlerContext ctx, MessageRecord msg, ByteBuf out)
  • 1.

msg 是收到的bean对象
然后将 bean 对象 序列化 byte[] 数组
out 是发送出去 byte[] 数组

Netty_04_消息协议设计与实战(实践类)_开发语言_19

解码函数里面拼装出一个 record 消息对象,如下:

解码,读进来,二进制流/byte[]数组 变为 对象
解码的目的对读进来二进制流处理,通过 ObjectInputStream 读进来,所以要将 二进制流/byte[]数组 变为 对象

protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
  • 1.

in 读进来 bytebuf 二进制数组
然后将 二进制数组 变为对象
放到 out 这个 list 里面

Netty_04_消息协议设计与实战(实践类)_开发语言_20

四、尾声

看懂代码就行,不难的。

源码下载:https://www.syjshare.com/res/XEE10LTG