Netty聊天系统(1)通过自定义协议实现客户端与服务器端通信

本文详细介绍了如何使用Netty自定义通信协议,包括设计通信协议的各个字段,如魔数、版本号、序列化算法、指令等。接着,文章讨论了Java对象的定义、序列化方法的实现以及编解码过程。通过创建自定义编解码器并将其加入到pipeline中,实现了登录功能。最后,文章展示了客户端与服务器端如何收发消息,以及如何处理这些消息。
摘要由CSDN通过智能技术生成

1 自定义实现客户端与服务器端通信的协议

1.1 通信协议的设计

自定义的通信协议需要哪些内容

1)魔数:第一个字段一般是魔数,一般固定的几个字节。一个PNG图片的编码中有固定数量固定内容的字节,用于表示这是一个PNG图片;Java的Class文件打头有一串魔数用于表示这是一个class文件;同样,我们的通信协议也是这么定义,服务器端或客户端收到数据包之后,会先读取魔数看看是不是我们定义的通信协议,只有是我们的通信协议时才能按照我们定义的规则正确读取数据。

2)版本号:用于一个字节表示,比如Http协议有1.0/1.1/2.0版本,用于标识当前的数据包使用的是哪个版本号

3)序列化算法:我们Netty通信过程中,使用Java对象进行数据传输,就一定会涉及到序列化与反序列化,用一个字节说明采用哪种序列化方式。

4)指令:你发给我这个数据包时要干什么。比如TCP协议中,SYN位置1就代表我是要跟你建立连接、FIN位置1就是代表我要断开连接。在聊天系统中,服务器收到客户端的数据包,指令位用于说明客户端发送这条数据包的目的,是要给某人发送消息呢还是要添加某人为好友呢还是怎么的…

5)数据长度:我发送给你的数据包的数据部分的长度是多少。解决TCP粘包拆包问题

6)数据部分:传输的数据

image-20200729102904574

1.2 通信协议的实现

1.2.1 Java对象

1)定义通信过程中传输的Java对象的抽象类

package maolaoke.top.netty.protocol;

import lombok.Data;

@Data
public abstract class Packet {
   
    //协议版本
    private Byte version = 1;

    //获取指令
    public abstract Byte getCommand();
}

2)~~定义一个枚举类,列出所有的指令。~~定义一个Command接口来模拟枚举,因为枚举默认是Integer类型,而我们要传输的是一个字节,用Byte来表示更合适。

public interface Command {
   
    Byte LOGIN_REQUEST = 1;  //表示这是一个登录请求
}

登录请求的Java类定义:

import maolaoke.top.netty.protocol.Command;

public class LoginRequestPacket  extends Packet{
   
    private Integer userId;

    private String username;

    private String password;
    
    @Override
    public Byte getCommand() {
   
        return Command.LOGIN_REQUEST;
    }
}

1.2.2 序列化

1)定义一个接口来模拟枚举,枚举所有的序列化标识。

public interface SerializerAlgorithm {
   
    byte JSON_SERIALIZER = 1;  //JSON序列化
}

2)定义一个序列化接口

public interface Serializer {
   
    //获取序列化方式
    byte getSerializerAlgorithm();

    //序列化方法
    byte[] serialize(Object object);

    //反序列化
    <T> T deserialize(Class<T> clazz, byte[] bytes);
}

3)实现JSON方式的序列化。

导入fastJson依赖包。

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.47</version>
</dependency>
import com.alibaba.fastjson.JSON;

public class JsonSerializer implements Serializer {
   
    @Override
    public byte getSerializerAlgorithm(){
   
        return SerializerAlgorithm.JSON_SERIALIZER;
    }

    @Override
    public byte[] serialize(Object object) {
   
        return JSON.toJSONBytes(object);
    }

    @Override
    public <T> T deserialize(Class<T> clazz, byte[] bytes) {
   
        return JSON.parseObject(bytes, clazz);
    }
}

1.2.3 编解码

PacketCodeC.java实现编解码,将发送的Java对象编码成标准的自定义通信协议的格式,将接收到的数据包解码成ByteBuf。

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import maolaoke.top.netty.protocol.Command;
import maolaoke.top.netty.protocol.packet.LoginRequestPacket;
import maolaoke.top.netty.protocol.packet.Packet;
import maolaoke.top.netty.protocol.serializer.JsonSerializer;
import maolaoke.top.netty.protocol.serializer.Serializer;

import java.util.HashMap;
import java.util.Map;

public class PacketCodeC {
   
    private static 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值