通信协议的设计如下图所示
定义通信过程中的Java对象
package com.example.demo.im;
import lombok.Data;
@Data
//自定义通讯协议
// 魔数(4字节)+版本号(1字节)+序列化算法(1字节)+指令(1字节)+数据长度(4字节)+数据(N字节)
public abstract class Packet {
/**
* 协议版本
*/
private Byte version = 3;
/**
* 指令
* @return
*/
public abstract Byte getCmd();
}
以客户端登录请求为例,定义登录请求数据包
package com.example.demo.im;
public interface Cmd {
//客户端发送登录请求
Byte LOGIN_REQUEST = 1;
//客户端收到登录响应
Byte LOGIN_RESPONSE = 2;
//客户端发消息请求
Byte MESSAGE_REQUEST = 3;
//客户端收消息响应
Byte MESSAGE_RESPONSE = 4;
}
package com.example.demo.im;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
//登录请求数据包
public class LoginRequestPacket extends Packet {
private Long userId;
private String userName;
private String password;
@Override
public Byte getCmd() {
return Cmd.LOGIN_REQUEST;
}
}
定义登录响应数据包
package com.example.demo.im;
import lombok.Data;
@Data
public class LoginResponsePacket extends Packet {
//原因
private String reason;
//是否登录成功
private Boolean success;
@Override
public Byte getCmd() {
return Cmd.LOGIN_RESPONSE;
}
}
定义序列化接口
package com.example.demo.im;
public interface SelfSerializable {
/**
* 序列化算法
*
* @return
*/
byte getSerializableAlgorithm();
/**
* java对象转二进制数据
*
* @param object
* @return
*/
byte[] serialize(Object object);
/**
* 二进制转为java对象
*
* @param clzz
* @param bytes
* @param <T>
* @return
*/
<T> T deserialize(byte[] bytes, Class<T> clzz);
SelfSerializable DEFAULT = new JsonSelfSerializable();
}
使用阿里的fastjson序列化
package com.example.demo.im;
public interface SerializableAlgorithm {
/**
* 阿里json序列化
*/
byte ALIJSON = 1;
}
package com.example.demo.im;
import com.alibaba.fastjson.JSON;
public class JsonSelfSerializable implements SelfSerializable {
@Override
public byte getSerializableAlgorithm() {
return SerializableAlgorithm.ALIJSON;
}
@Override
public byte[] serialize(Object object) {
return JSON.toJSONBytes(object);
}
@Override
public <T> T deserialize( byte[] bytes,Class<T> clzz) {
return JSON.parseObject(bytes,clzz);
}
}
编解码
package com.example.demo.im;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
// 魔数(4字节)+版本号(1字节)+序列化算法(1字节)+指令(1字节)+数据长度(4字节)+数据(N字节)
public class PacketCodec {
public static final int MAGIC = 12345678;
public static final PacketCodec INSTANCE = new PacketCodec();
public void encode(ByteBuf byteBuf, Packet packet) {
byte[] bytes = SelfSerializable.DEFAULT.serialize(packet);
byteBuf.writeInt(MAGIC);