自定义应用层通信协议

自定义应用层通信协议(1)

 

标签:通信协议 要素 

1.通信协议的概念及其要素

OSI开放互联参考模型中,对等实体之间数据单元在发送方逐层封装,在接收方的逐层解析。发送方N层实体从N+1层实体得到的数据包称为服务数据单元(Service Data UnitSDU)。N层实体只将其视为需要本实体提供服务的数据,将服务数据单元进行封装,使其成为一个对方能够理解的数据单元(Protocol Data UnitPDU),封装过程实际上是为SDU增加对等实体间约定的控制信息(Protocol Control InformationPCI)的过程。

为了保证网络的各个功能的相对独立性,以及便于实现和维护,通常将协议划分为多个子协议,并且让这些协议保持一种层次结构,子协议的集合通常称为协议簇。

网络协议的分层有利于将复杂的问题分解成多个简单的问题,从而分而治之。各层的协议由各层的实体实现,通信双方对等层中完成相同协议功能的实体称为对等实体。对等实体按协议进行通信,所以协议反映的是对等层的对等实体之间的一种横向关系,严格地说,协议是对等实体共同遵守的规则和约定的集合。

通信协议精确地定义了双方通信控制信息和解释信息:发送方能将特定信息(文本、图片、音频、视频)按协议封装成指定格式的数据包,最终以串行化比特流在网络上传输;接收方接收到数据包后,根据协议将比特流解析为本地化数据,从而获取对方发送过来的原始信息。

通信协议包括三个要素:

1)语法:规定了信息的结构和格式;

2)语义:表明信息要表达的内容;

3)同步:规则涉及双方的交互关系和事件顺序。

整个计算机网络的实现体现为协议的实现,TCP/IP协议是Internet互联网的核心协议。

2.通信协议开发步骤

1) 协议的开发主要包括协议设计、协议形式描述、协议实现和协议一致性测试。协议的开发过程与步骤如图1所示。

    1 协议开发过程与步骤

2协议设计过程中的分组发送接收模型如图2所示。

2协议设计过程中的分组发送接收模型

3)协议的一致性测试

协议的一致性测试是指测试协议能否按照预想的控制策略实现正确的通信,主要体现在数据包通过信道从信源传送到信宿后,信宿能够根据协议正确的解析出原始信息。

协议的一致性测试如图3所示。

3 协议一致性测试环境

根据测试环境的可以分为局部测试和分布式测试,如图4所示。

4局部测试法、分布式测试法

3.数据包和数据报

为方便描述自定义协议,还是借用数据包和数据报来描述封装数据单元和传输数据单元,但这里的数据包和数据报完全不同于TCP/IP架构中的PacketDatagram概念。

下文所述的数据包指封装的基本单位,以TLVType-Length-Value)格式封装基本消息单位;数据报Package是传输的基本单位,头部包含序列号和命令信息。接收端根据命令信息分辨事件类型,做出不同的解析。报文实体是多个TLV数据包组成的链表。

 

 

 

4.数据包TLV的设计

从应用层HTTP协议,到超文本置标语言HTMLHyperText Mark-up Language),再到可扩展置标语言XMLExtensible Markup Language),它们提供了数据的格式化存储、传输和格式化显示的规范,是网络通信的基石。然而HTTP协议以及HTML/XML置标语言的本质就是定义一堆标签(Tag)对数据进行串行化序列化,然后接收方再根据标签解析、还原数据。

自定义通信协议的关键是对数据包的合理构造(construct)和正确解析(parse),即制定编解码规则。

抽象语法标记ASNAbstract Syntax Notation BER的长度确定的编码方式,由3部分组成Identifier octetsLength octetsContents octets,实际上这就是一中TLVType-Length-Value)模型:类型字段(TypeTag)是关于标签和编码格式的信息;长度字段(Length)定义数值的长度; 内容字段(Value)表示实际的数值。

因此,一个编码值又称TLV三元组。编码可以是基本型或结构型,如果它表示一个简单类型的、完整的显式值,那么编码就是基本型(primitive);如果它表示的值具有嵌套结构,那么编码就是结构型 (constructed)。

TLV编码就是指对TypeTag)、LengthValue进行编码,形成比特流数据包;解码是编码的逆过程,是从比特流缓冲区中解析还原出原始数据。

采用C++编程语言设计TLV协议类,其类视图如图5所示。

5 CTLV类视图

目前只提供设置整形值(int型)的setValue_Int和设置字符串值(C_String型)的SetValue_Cstring两个接口。

TLV将数据封装成包的格式如表1所示。

1 TLV包格式

TLV

头部

包实体

m_dwTag

m_nLen

m_pValue

   

TLV的接口说明:

1)值类型标签m_vtTag是内部辅助枚举变量,它根据构造TLV时传递的服务类型标签m_dwTag来确定。

2TLV::m_nLen在为TLV设置具体值时确定。

3TLV包的封装:

1)使用Tag参数创建一个TLV对象后,调用TLV::setValue_*方法为TLV填充具体值;

2)调用TLV::toBuffer方法打包到缓冲区streamBuffer

4TLV包的解析:创建一个TLV对象后,调用TLV::fromBuffer方法从缓冲区streamBuffer解析出TLV

5)封装和解析涉及到本机字节顺序和网络字节顺序的转换问题。

6)调用TLV::setValue_*方法填充TLV时,统一字节边界数为4

5.数据报Package的设计

不同于底层的数据包/数据报只是对数据层次的封装解析,实际应用程序是以事件驱动的,因此必须注册不同的信令(事件类型标签),然后填充到数据报中。接收端根据信令做出相应的事件处理。

例如在C/S通信系统中,客户端往往要先登录,通过服务器端的校验才能进行后续通信。因此客户端运行后,需要构造并向服务器端发送含有LOGIN信令的包含用户名字符串strUserName和密码字符串strPassWord的数据报;服务器端解析LOGIN信令后做校验处理,然后发送含有LOGIN_RESPONSE信令和校验结果的回执数据报给客户端。

采用C++编程语言设计Package类,其类视图如图6所示。

6 CPackage类视图

Package类将TLV封装成包的格式如表2所示。

2 Package包格式

Package

头部

序列号

包实体

m_nCmdLen

m_dwCmdID

m_dwCmdState

m_nSeqNo

Count*Tlv

     

Package的接口说明:

1Package::m_nCmdLen是整个Package包的长度,将其作为首个字段的好处在于当传送大数据包时,接收方可以根据数据长度来控制读状态,从而将一个大数据包分批接收。

2Package::m_nCmdLen在构造函数中初始化为16,在调用Package::addTLV方法填充包实体时增长。

3Package包的封装:

1)创建Package对象后,调用Package::setHeader方法填充头部信令;

2)创建TLV对象并填充数据,再调用Package::addTLV方法填充包实体;

3)调用Package::toBuffer方法将Package打包到缓冲区streamBuffer

4Package包的解析:

1)先创建一个Package对象,调用Package::fromBuffer方法从缓冲区streamBuffer先解析出Package的头部和序列号,再从剩余缓冲区中解析出TLV并将其串行化到链表。

2)调用Package::getTLV方法根据Tag从链表中查找具体TLV包,再调用TLV::getValue方法取得具体值。

5Package::toBuffer方法和Package::fromBuffer方法主要遍历Package::m_TLV_List列表,然后调用TLV::toBuffer方法和TLV::fromBuffer方法解析出TLV数据单元。

TLV数据包的功能测试(主要是本地测试)

鉴于实际通信数据最后都要转换成比特流,故只测试发送字符串类型的变量,仅测试协议能否正确打包、解析。其他类型的普通数据都可以转换成字符串传输,最后,接收方根据m_dwTag确定值类型m_vtTag,解析出具体值。

TLV::setValue_C_String方法填充TLV的测试,需要考虑字节对齐问题。对于长度为4字节倍数的C状态字符串,打包时省去末尾的‘/0’结束标志符。需要测试长度非4倍数的字符串和长度为4倍数的字符串。

经本地测试,调用TLV::setValue_Int方法和TLV::setValue_C_String方法构造整形和字符串时,能够正确封装、正确解析。

Package数据报的功能测试,主要是将TLV组合成包,然后添加信令,完成特定的通信。对登陆LOGIN和发送消息SUBMIT_SM的测试表明Package协议能正确封装、正确解析。

在实际项目中使用Package通信协议,对于稍大一点的数据块需要控制好读的步骤,以便能接收整包完整的信息。

参考:

《计算机网络协议和实现技术》 鲁士文

编号 文件名称 cwts-specs-001 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:名语术语 cwts-specs-002 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:概述 cwts-specs-003 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:物理信道传输信道到物理信道的映射 cwts-specs-004 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:信道编码与复用 cwts-specs-005 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:扩频与调制 cwts-specs-006 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:物理层过程 cwts-specs-007 IMT-DS FDD(WCDMA)系统无线接口物理层技术规范:物理层测量 cwts-specs-008 IMT-DS FDD(WCDMA)系统无线接口层2技术规范:物理层向上层提供的服务 cwts-specs-009 IMT-DS FDD(WCDMA)系统无线接口层2技术规范:MAC协议 cwts-specs-010 IMT-DS FDD(WCDMA)系统无线接口层2技术规范:RLC协议 cwts-specs-011 IMT-DS FDD(WCDMA)系统无线接口层2技术规范:PDCP协议 cwts-specs-012 IMT-DS FDD(WCDMA)系统无线接口层2技术规范:BMC协议 cwts-specs-013 IMT-DS FDD(WCDMA)系统无线接口层3技术规范:RRC协议 cwts-specs-014 IMT-DS FDD(WCDMA)系统Iu接口技术规范:概述 cwts-specs-015 IMT-DS FDD(WCDMA)系统Iu接口技术规范:层1技术要求 cwts-specs-016 IMT-DS FDD(WCDMA)系统Iu接口技术规范:信令传输 cwts-specs-017 IMT-DS FDD(WCDMA)系统Iu接口技术规范:RANAP信令 cwts-specs-018 IMT-DS FDD(WCDMA)系统Iu接口技术规范:数据传输传输信令 cwts-specs-019 IMT-DS FDD(WCDMA)系统Iu接口技术规范:用户平面协议 cwts-specs-020 IMT-DS FDD(WCDMA)系统Iub接口技术规范:概述 cwts-specs-021 IMT-DS FDD(WCDMA)系统Iub接口技术规范:层1技术要求 cwts-specs-022 IMT-DS FDD(WCDMA)系统Iub接口技术规范:信令传输 cwts-specs-023 IMT-DS FDD(WCDMA)系统Iub接口技术规范:NBAP信令 cwts-specs-024 IMT-DS FDD(WCDMA)系统Iub接口技术规范:用于CCH数据流的数据传输传输信令 cwts-specs-025 IMT-DS FDD(WCDMA)系统Iub接口技术规范:用于CCH数据流的用户平面协议 cwts-specs-026 IMT-DS FDD(WCDMA)系统Iur接口技术规范:概述 cwts-specs-027 IMT-DS FDD(WCDMA)系统Iur接口技术规范:层1技术要求 cwts-specs-028 IMT-DS FDD(WCDMA)系统Iur接口技术规范:信令传输 cwts-specs-029 IMT-DS FDD(WCDMA)系统Iur接口技术规范:RNSAP信令 cwts-specs-030 IMT-DS FDD(WCDMA)系统Iur接口技术规范:用于CCH数据流的数据传输传输信令 cwts-specs-031 IMT-DS FDD(WCDMA)系统Iur接口技术规范:用于CCH数据流的用户平面协议 cwts-specs-032 IMT-DS FDD(WCDMA)系统Iub/Iur接口技术规范:用于DCH数据流的数据传输传输信令 cwts-specs-033 IMT-DS FDD(WCDMA)系统Iub/Iur接口技术规范:用于DCH数据流的用户平面协议 cwts-specs-034 TD-SCDMA系统无线接口物理层技术规范 cwts-specs-035 TD-SCDMA系统无线接口层2技术规范 cwts-specs-036 TD-SCDMA系统无线接口层3-RRC技术规范 cwts-specs-037 TD-SCDMA系统Iu接口技术规范 cwts-specs-038 TD-SCDMA系统Iub接口技术规范 cwts-specs-039 TD-SCDMA系统Iur接口技术规范 cwts-specs-040 TD-SCDMA系统基站设备无线收发特性技术规范 cwts-specs-041 TD-SCDMA系统用户终端设备无线收发特性技术规范 CWTS发布的研究报告列表 cwts-reports-001 IMT-DS FDD(WCDMA)系统连接模式下的层间过程(25.303)标准研究报告 cwts-reports-002 IMT-DS FDD(WCDMA)系统空闲模式下UE的流程连接模式下小区重选流程(25.304)标准研究报告 cwts-reports-003 IMT-DS FDD(WCDMA)系统无线资源管理RRM研究报告 cwts-reports-004 IMT-DS FDD(WCDMA)系统无线资源管理RRM研究报告 cwts-reports-005 IMT-DS FDD(WCDMA)系统UE无线接入能力研究报告
<think>嗯,用户现在想了解如何设计实现自定义应用层协议,之前他们问的是Java游戏模组开发,现在转向了网络协议设计,这可能是因为他们在开发模组时需要处理网络通信的问题。需要结合他们提供的三个引用内容,这些引用提到了自定义协议的必要性、序列化、TCP实现以及XML格式的例子。首先,我得明确用户的需求。他们可能是在开发游戏模组时需要让客户端服务器通信,比如同步玩家位置、物品信息等,所以需要自定义协议。引用里提到了网络版计算器的例子,使用序列化反序列化,还有JSONXML的结构,这些可以作为参考。 接下来,我得整理设计自定义协议的步骤。根据引用内容,关键点包括协议结构设计(报文格式、字段定义)、序列化方法选择、传输层协议选择(如TCP)、错误处理等。需要分步骤讲解,比如确定需求、设计报文、选择序列化方式、实现编解码、测试等。 然后要考虑如何将引用中的例子融入进去。比如网络计算器使用JSON的例子,可以说明序列化的具体实现。还有XML格式的请求,展示不同格式的应用。可能需要比较不同序列化方式的优缺点,帮助用户选择合适的方法。用户可能遇到的问题包括如何处理粘包、数据校验、协议升级等,这些需要涵盖在实现注意事项里。另外,性能优化方面,比如压缩数据,也要提到。最后,生成相关问题,引导用户深入思考协议设计中的具体问题,比如如何选择序列化格式、处理粘包、设计校验机制等。需要确保问题与用户的实际开发场景相关,帮助他们解决可能遇到的挑战。</think>### 自定义应用层协议设计与实现指南 基于TCP实现自定义协议需要明确定义**报文结构**、**序列化方式****通信流程**。以下是关键步骤与示例: --- #### 一、协议设计核心要素 1. **报文格式** - **定界符**:使用特殊字符(如`<requset>`/`</requset>`)或长度前缀标识报文边界[^3] - **字段定义**:结构化数据(如用户ID、坐标位置),支持嵌套或键值对形式[^3] - **示例XML格式**: ```xml <request> <userId>1234</userId> <position>100 80</position> </request> ``` 2. **序列化与反序列化** - **二进制协议**:直接编码整数/浮点数(性能高但可读性差) - **文本协议**:JSON/XML(易调试,但传输效率较低)[^1] - **示例JSON序列化**: ```json { "userId": 1234, "position": [100, 80] } ``` 3. **传输层选择** - **TCP协议**:保证可靠传输,需处理粘包问题(通过长度字段或分隔符)[^2] - **UDP协议**:低延迟但需自行处理丢包重传 --- #### 二、实现步骤(以网络计算器为例) 1. **定义协议规范** - 请求格式:`{"op": "+", "a": 5, "b": 3}` - 响应格式:`{"result": 8}` 2. **实现序列化工具** ```java // 使用Jackson库实现JSON序列化 ObjectMapper mapper = new ObjectMapper(); String request = mapper.writeValueAsString(new CalculatorRequest("+", 5, 3)); byte[] data = request.getBytes(StandardCharsets.UTF_8); ``` 3. **封装Socket通信** ```python # TCP服务端接收逻辑(处理粘包) def recv_all(sock, length): data = b'' while len(data) < length: packet = sock.recv(length - len(data)) if not packet: return None data += packet return data ``` 4. **协议解析与处理** ```java // 反序列化并执行计算 CalculatorRequest req = mapper.readValue(inputStream, CalculatorRequest.class); double result = calculate(req.op, req.a, req.b); String response = mapper.writeValueAsString(new CalculatorResponse(result)); ``` --- #### 三、实现注意事项 1. **粘包处理** - 方案1:固定长度头部(如4字节表示后续数据长度) - 方案2:使用分隔符(如`\r\n\r\n`) 2. **数据校验** - 添加校验字段(如CRC32或MD5哈希) - 示例:`{"data": ..., "checksum": "a1b2c3"}` 3. **协议升级** - 版本号字段:`{"version": 2, ...}` - 向后兼容性设计 --- #### 四、性能优化技巧 1. **二进制协议优化** - 使用Protobuf/FlatBuffers替代JSON - 压缩算法(如gzip) 2. **TCP参数调优** - 设置合理的`SO_SNDBUF``SO_RCVBUF` - 启用Nagle算法(需权衡延迟与吞吐量) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值