首页 > 其他分享 >自定义应用层通信协议结构消息的编码方式

自定义应用层通信协议结构消息的编码方式

时间:2023-11-28 22:12:41浏览次数:45  
标签:自定义 报文 通信协议 消息 长度 编码方式 数据包 应用层

应用层通信协议设计

 

一、应用层通信协议概述

TCP/UDP是基于字节流的传输层通信协议,对于其的编程是基于IO流编程,所谓“流”,就是没有界限的一长串二进制数据。TCP/UDP作为传输层协议,并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分。所以在业务上一个完整的数据包在进行传输时,可能会被拆分成多个包进行发送,也可能将很多小的数据包封装成一个大的数据包发送,也就是TCP/UDP的拆包和粘包问题。如果直接序列化发出数据包,接收方无法知道一个完整的报文从哪里开始,到哪里结束,这个问题需要通过上层的应用协议设计来解决。

二、业界主流协议调研

目前业界主流的协议的解决方案如下:

1.消息定长:报文长度固定,例如每个报文的长度固定为 200 字节,如果不够空位补空格,接受方每次拿 200 字节。

2.使用特殊分隔符分隔:例如每条报文结束都添加回车换行符作为报文分隔符,接收方读到回车换行符则分割出报文。

3.分为消息头和消息体:消息头包含消息的长度,接收方从消息头拿到消息长度,就知道剩下的报文是多少字节了。

4.更复杂的自定义应用层协议。

三、自定义应用层通信协议结构

综合以上内容,本项目工程中定义了一个应用层通信协议,结构如下:

 

 

如上图所示,发送的数据由消息头(header)和主体(body)组成,消息头包括:

  1. 报文类型:不同类型的报文在服务器中执行不同的指令和功能。
  2. 数据长度:数据长度由消息头长度加上数据主体内容的长度组成。

消息主体为定长的数据缓冲区(但传输的消息长度是不定的)。

为了实现上述的结构,定义了两个结构体,分别是消息头结构体和消息结构体,消息头结构体嵌套在消息结构体中,同时定义了一个枚举类型,用于定义通信所需的各种消息类型。

 

 

 

不同类型的消息的编码方式如下表所示:

 


可以看到,报文整体由$分隔的单个字符串组成,消息头的组成基本相同,以logIn为例,报文的第一位是消息类型LogIn,第二位是不包括消息头的消息长度,之后依次是用户名和密码。而在Getfrdlist中,除了消息头,好友人数之外,循环编码了由uid,uname,usex,role组成的字符串,各项之间用#分隔。

 

 

协议由服务端和客户端双方遵守,共用一套相同的编码和解码函数,编码即是按照前一页的协议具体内容拼接成字符串。解码需要读取消息头,先判断消息类型,用于区分不同消息以确定不同的解码方式,然后获取消息长度,用于对报文进行长度校验,以确保数据发送的安全性和完整性。

 

四、总结

在我看来,通信协议的设计主要需要满足三个点:

  1. 统一:协议由服务端和客户端双方遵守,共用一套相同的编码和解码函数。
  2. 区分:用消息头来区分不同的消息类型,用于判断是什么类型的消息,选择对应的解码。
  3. 安全:要对数据包的完整性进行校验,进行长度的校验是最基本的校验,常见的检验方式由checksum校验和、CRC校验等类型。

 

标签:自定义,报文,通信协议,消息,长度,编码方式,数据包,应用层
From: https://www.cnblogs.com/Leo_wl/p/17863226.html

相关文章

  • springboot 自定义响应体大小测试接口
    @ResponseBody@RequestMapping("/def/response/body/service")publicStringBuilderdefResponseBodyService(@RequestParam(name="count")Integercount,HttpServletRequestHttpRequest)throwsInterruptedException{  StringbaseStr="0......
  • Qt给QRadioButton设置自定义样式
    一、概述做一个好看的QRadioButton。可以选中,取消选中。二、代码示例1.样式QRadioButton::indicator::unchecked{border-image:url(images/user_protocol_uncheck.webp);}QRadioButton::indicator::checked{border-image:url(images/user_protocol_......
  • C# 比使用app.config,用自定义的ConnectionString
    usingSystem.Data;usingSystem.Data.SqlClient;usingSystem.IO;usingSystem.Reflection;namespaceAssist{publicclassContextHelper{publicstaticstringConnectionString;publicstaticstringSerializePath=Path.GetDirector......
  • 自定义滚动条样式
    在要添加滚动条的标签样式中添加,注意lang="less“1::-webkit-scrollbar{2width:12px;3background-color:#f1f1f1;4}5/*定义滑块内阴影+圆角*/6::-webkit-scrollbar-thumb{7background-color:#cac8c8;8border:2pxsolid#f1f1f......
  • 直播系统代码,Android自定义View实现呼吸灯效果
    直播系统代码,Android自定义View实现呼吸灯效果自定义View的属性定义attrs.xml如下: <resources>  <declare-styleablename="BreathView">    <attrname="centerCircleRadius"format="dimension"/>    <attrname="circleCol......
  • 直播平台搭建,自定义气泡效果(BubbleView)
    直播平台搭建,自定义气泡效果(BubbleView) packagecom.example.myapplication;importandroid.content.Context;importandroid.graphics.BlurMaskFilter;importandroid.graphics.Canvas;importandroid.graphics.Color;importandroid.graphics.Paint;importandroid.graphics.......
  • Qt自定义QLineEdit
    一、概述自定义QLineEdit,让QLineEdit变的好看一点。实现效果:1.普通输入(可以输入汉字、字符、数字)2.只能输入数字3.密码模式输入框二、代码示例1.创建EditText.h和EditText.cpp[默认样式]#include"EditText.h"EditText::EditTex......
  • Qt创建一个自定义QPushButton
    一、概述使用Qt创建一个通用的QPushButton。应用一些样式把按钮做的好看一些。步骤:1.新建一个Button类然后继承QPushButton2.设置Button的通用样式(ps:使用.qss文件的形式应用样式)3.个性化设置不同的样式4.做一个圆角按钮、带图标按......
  • SpringCloud——自定义断言工厂
    目录场景:用户的请求头中需要有指定的用户名和密码才能访问。断言工厂参考系统AfterRoutePredicateFactory写法。packagecom.zjw.factory;importlombok.Getter;importlombok.Setter;importorg.springframework.cloud.gateway.handler.predicate.AbstractRoutePredi......
  • 【2023CANN训练营第二季】——Ascend C自定义算子工程介绍及实验
    一、自定义算子工程介绍与创建自定义算子工程是一个包含用户编写的host侧和kerne|侧算子实现文件的,用于编译和安装自定义算子run包的工程框架。CANN软件包中提供了工程创建工具msopgen,开发者可以输入算子原型定义文件生成AscendC算子开发工程。需要编写AddCustom算子的原型定义......