开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情
客户端与服务端通信协议编解码
通信协议的设计
魔数用来标识是否是属于这个协议的请求,不是的话直接关闭连接
通信协议的实现
先实现序列化接口
具体看demo1包。
解码的流程如下:
- 我们假定
decode方法传递进来的ByteBuf已经是合法的(在后面小节我们再来实现校验),即首四个字节是我们前面定义的魔数0x12345678,这里我们调用skipBytes跳过这四个字节。 - 这里,我们暂时不关注协议版本,通常我们在没有遇到协议升级的时候,这个字段暂时不处理,因为,你会发现,绝大多数情况下,这个字段几乎用不着,但我们仍然需要暂时留着。
- 接下来,我们调用
ByteBuf的 API 分别拿到序列化算法标识、指令、数据包的长度。 - 最后,我们根据拿到的数据包的长度取出数据,通过指令拿到该数据包对应的 Java 对象的类型,根据序列化算法标识拿到序列化对象,将字节数组转换为 Java 对象,至此,解码过程结束。
可以看到,解码过程与编码过程正好是一个相反的过程。
实战:实现客户端登陆
客户端处理登录请求
public void channelActive(ChannelHandlerContext ctx) {
System.out.println(new Date() + ": 客户端开始登录");
// 创建登录对象
LoginRequestPacket loginRequestPacket = new LoginRequestPacket();
loginRequestPacket.setUserId(UUID.randomUUID().toString());
loginRequestPacket.setUsername("flash");
loginRequestPacket.setPassword("pwd");
// 编码
ByteBuf buffer = PacketCodeC.INSTANCE.encode(ctx.alloc(), loginRequestPacket);
// 写数据
ctx.channel().writeAndFlush(buffer);
}
实战:实现客户端与服务端收发消息
这一小节,我们来实现客户端与服务端收发消息,我们要实现的具体功能是:在控制台输入一条消息之后按回车,校验完客户端的登录状态之后,把消息发送到服务端,服务端收到消息之后打印并且向客户端发送一条消息,客户端收到之后打印。