【Betty】通信协议 —— ENetCommand 与 NetMessage

shadowLogo

网络通信 中,
不,应该说是在 通信 中,我们都需要制定 通信协议
只有制定了通信协议,双端的消息才能被正确地解析,才能进行双端正常通信

那么,什么是 通信协议 呢?

通信协议·定义:

通讯协议 又称 通信规程,是指 通信双方数据传送控制 的 一种约定
约定中包括对 数据格式同步方式传送速度传送步骤检纠错方式 以及 控制字符定义 等问题做出统一规定
通信双方 必须 共同遵守,它也叫做 链路控制规程

那么,本人用一句话来概括:

通信协议,就是 通信双方 制定的 信息传输格式


本人在专栏总集篇博文中,也讲过:

《Betty》是一个 网络通信框架

根据本人在上文中所讲解的概念,作为一个通信框架,就要制定 通信协议

那么,本人就来展示下 Betty 中,体现通信协议 的 “信息载体”:

代码实现:

首先是 ENetCommand 枚举

ENetCommand:

为什么要在制定通信协议的过程中,使用枚举呢?
答曰

每一次向对端发送消息,需要先声明是 什么类型请求/响应
(例如:请求连接、私聊... ...)

相应代码

package edu.youzg.betty.protocol;

public enum ENetCommand {
	SERVER_OUT_OF_ROOM,	//服务器处理的客户端数已满
	WHO_ARE_YOU,	//连接时,服务器向客户端索要必要的信息
	I_AM,	//客户端将服务器索要的信息传给服务器
	ENSURE_ONLINE,	//服务器允许客户端登录
	OFFLINE,	//客户端请求下线
	
	TO_ONE,	//客户端单发消息
	TO_OTHER,	//客户端群发消息
	
	REQUEST,	//客户端申请某操作/资源
	RESPONSE,	//服务器对客户端的申请做出响应

	SERVER_FORCE_DOWN,	//服务器异常宕机
	
	SERVER_FORCE_CLIENT_DOWN,	//服务器强制客户端下线
	
	SEND_MESSAGE_TO_SERVER,	//客户端发送信息给服务器
}

以上枚举只是 通信双方最基本的操作类型
若是我们想要实现些扩展功能,比如 超时重传心跳检测 等扩展功能,可以在其中增加相应的 成员属性


那么,消息的操作类型明确了
接下来,本人就来讲解下 完整的 协议(消息格式) —— NetMessage类

NetMessage:

由于 消息内容 暂时只需要包含 基本信息
所以,本人将信息组成规定为如下格式:

  • 操作类型(Ecommand)
  • 具体操作描述信息(action)
  • 执行该动作所需参数(parameter)

那么,根据上述思想,本人来编写下 NetMessage类:

package edu.youzg.betty.protocol;

public class NetMessage {
    ENetCommand command;
    String action;
    String parameter;

    public NetMessage() {
    }

    /**
     * 伪decoding</br>
     * 解析 对端发来的消息
     * @param message 对端发来的消息
     */
    public NetMessage(String message) {
        int colonIndex = message.indexOf(':');
        String strCommand = message.substring(0, colonIndex);
        this.command = ENetCommand.valueOf(strCommand);

        message = message.substring(colonIndex + 1);
        colonIndex = message.indexOf(':');
        String strAction = message.substring(0, colonIndex).trim();
        this.action = strAction.length() <= 0 ? null : strAction;

        this.parameter = message.substring(colonIndex + 1);
    }

    public ENetCommand getCommand() {
        return command;
    }

    public NetMessage setCommand(ENetCommand command) {
        this.command = command;
        return this;
    }

    public String getAction() {
        return action;
    }

    public NetMessage setAction(String action) {
        this.action = action;
        return this;
    }

    public String getParameter() {
        return parameter;
    }

    public NetMessage setParameter(String parameter) {
        this.parameter = parameter;
        return this;
    }

    /**
     * 伪encoding</br>
     * 将消息格式化,便于之后的处理和传输
     * @return
     */
    @Override
    public String toString() {
        // 假设三个成员的值分别是:
        // command : CLIENT_ONLINE
        // action : studentLogin
        // parameter : "id=123456,password=54321"
        // 希望在网络上传递的信息如下:
        // CLIENT_ONLINE:studentLogin:id=123456,password=54321
        return command + ":" + (action == null ? " " : action) + ":" + parameter;
    }

}

那么,本人对于上述代码,做几点说明

toString单参构造伪编解码
因为 真正的编解码,是将 我们正常人能够看懂的信息,和 相应的二进制数据 进行相互转换
而这里的 伪编解码,只是简单地将 通信信息的对象,和 相应的字符串 进行转换
此处 只是为了 模仿网络通信的流程

那么,本篇博文的内容,在这里就讲解完毕了
相信在之后的学习中,同学们会发现 通信协议 的重要性!

posted @ 2020-04-22 00:11  在下右转,有何贵干  阅读(122)  评论(0编辑  收藏  举报