Netty(3)

60 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情

客户端与服务端通信协议编解码

通信协议的设计

image.png

魔数用来标识是否是属于这个协议的请求,不是的话直接关闭连接

通信协议的实现

先实现序列化接口

具体看demo1包。

解码的流程如下:

  1. 我们假定 decode 方法传递进来的 ByteBuf 已经是合法的(在后面小节我们再来实现校验),即首四个字节是我们前面定义的魔数 0x12345678,这里我们调用 skipBytes 跳过这四个字节。
  2. 这里,我们暂时不关注协议版本,通常我们在没有遇到协议升级的时候,这个字段暂时不处理,因为,你会发现,绝大多数情况下,这个字段几乎用不着,但我们仍然需要暂时留着。
  3. 接下来,我们调用 ByteBuf 的 API 分别拿到序列化算法标识、指令、数据包的长度。
  4. 最后,我们根据拿到的数据包的长度取出数据,通过指令拿到该数据包对应的 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);
}

实战:实现客户端与服务端收发消息

这一小节,我们来实现客户端与服务端收发消息,我们要实现的具体功能是:在控制台输入一条消息之后按回车,校验完客户端的登录状态之后,把消息发送到服务端,服务端收到消息之后打印并且向客户端发送一条消息,客户端收到之后打印。