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

本文详细介绍了如何自定义客户端与服务器端的通信协议,包括设计要点如魔数、版本号、序列化算法、指令、数据长度和数据部分。在实现阶段,讨论了Java对象的定义、序列化策略以及利用FastJson实现JSON序列化,并阐述了编解码过程以确保数据的正确传输。
摘要由CSDN通过智能技术生成

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

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

2 通信协议的实现

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;
    }
}

2.2 序列化

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

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

2)定义一个序列化接口

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

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

  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值