Author [email protected]
Date Aug. 19, 2023
Description 设计一个网络通信协议
大多数时候,并不需要进行协议设计,只需要使用成熟的协议就行了。但架不住少数时候的存在,所以就需要了解如何去设计一个协议。
实际上协议工程学是一门专门的学科,而且互联网络常见的协议都是很好的样例。IETF作为互联网络标准化协议组织,本来以为他们的协议设计规范就会比较权威。结果以design protocol为关键词去RFC Editor网站搜索,可以出来17个结果。但是RFC这个网站有时候相关的RFC如果不放宽限制就会错过。而且很多古老的协议也有可能已经失去了价值。所以得放宽一下搜索条件为design,这时候会有55条结果,太多不放图了。这个时候,不特定于具体协议的设计原则,可能只有RFC3117以及更古老的协议了。
emmm,没办法,还是求助于搜索引擎吧。以design protocol principle ietf
为关键字,搜索出来了RFC5218、RFC5704。好吧,看来协议设计原则还是需要特定于协议的。
算了算了,还是看slides吧。
选择通信模式和数据传送方式
通信的模式可以分为两类,一类是client-server,另一类是peer-peer。前者一般是client发起通信请求,后者响应通信请求。而后者则是谁都可以发起通信请求,另一端响应通信请求。
数据传输的模式可以分为unicast(one-to-one),multicast(one/more-to-more),broadcast(one/more-to-all)。这些可能用于通信的某一个阶段。例如IPv4 ARP采用broadcast查询下一跳的mac地址;IPv6通过将Solicited-node multicast地址与IPv6 Neighbor Discovery协议相结合,能够有效减少广播范围。正常的通信请求则是Unicast方式进行。
设立设计目标
所谓设立设计通信协议的目标,就是定义通信框架
- fast是不是首要的选择?(UDP)
- 是否需要可靠的交换,即需要对发送数据的确认(TCP)
- 实体对端验证的重要性
- 是否对通信进行加密。需要什么程度的授权。
- 多少种类型的实体将会参与通信。是否需要一种互相通信的模式。
- 是否具有连通性以及带宽的限制。
- 是否需要维护通信信道,无连接的通信模式是否更加合适
- 是否需要复杂错误处理
一个通信协议应该是:
- 简单:就是遵循keep it simple and stupid(KISS)原则,不要使得简单任务复杂化;不要为做同一件事情提供两种方式(好像也不完全遵循这个吧,还不太理解)
- 规模可扩展(scalable):评估每个server可以连接的client规模。平衡每个实体的职责(emmm,理解不了)
- 高效:最小化命令开销,最小化数据流量。
- 功能可扩展(extensible):协议要可演进,为后续的功能扩展留出空间,不要过度为了扩展而扩展。
选择消息格式
两种方式:面向文本的协议以及面向二进制的协议。
面向文本的协议需要所有的消息都是可读的。这样对于人类是可读可监控的,非常灵活易于扩展,易于调试。但是这样子也相当于是明文传输的,对于未授权用户也是可读的,而且编码问题也会变得复杂起来,同时可能会让消息极度膨胀。
面向二进制的协议是二进制数据结构块。结构化数据的更好的方式,非常适用于大且复杂的数据的传输,消息会比较小。但是难以阅读、调试或者测试。需要考虑数据在hosts以及网络中的表示形式,例如大小端问题。
设计消息结构:消息格式、字段、类型
设计消息是协议设计中一个非常重要的方面。将会影响到通信中的各个方面:规模可扩展性、高效性、简单性、功能可扩展性。
设计涉及到消息类型和消息结构。
消息类型对应通信的完全不同的方面,消息类型可以归类到command、data transfer、control三个分类内。每种分类可能都包含几种类型的消息类型。
- Command消息用于定义通信实体所处的阶段:开始或者结束、描述通信阶段、状态改变、资源交换。
- Data Transfer消息用于携带数据。基本都是作为响应方对请求方的命令进行响应。data一般是经过了分片分散在各个消息中,需要接收端根据协议进行组装,例如IPv4的分片。但是这种消息也不仅仅是传输消息,还包含了二进制数据类型、结构化数据的布局、数据大小、分片消息的偏移量、序号信息。
- Control消息控制实体间的通信过程。描述协作关系(接收确认、请求重传)、取消或者打断数据传输、可用性监测等。
消息的结构一般分为header和body。
- Header包含了结构化的字段,用于描述真实的数据,包括消息类型、command、body size、接收端信息、序号信息、重传数量等。
- Body是真实要传输的数据,可以是command的参数或者data payload。
- 一般Header的size是固定的,而body的size则要么固定要么取决于Header中指定的body size。
设计通信规则(sequences)
通信双方要知道先干啥后干啥。一般应该都是协议有限状态机(finite state machine,fsm)形式。定义了commands、data、control消息的顺序。
可以使用sequence diagram进行描述,也可以使用state diagram进行描述。例如TCP的三次握手协议以及四次挥手协议。
设计了协议就需要文档标准化。虽然应该描述的清晰、完整、易于理解,没有歧义、可维护。但这一步反而恰恰是最为困难的。因为涉及到多方博弈,想要让所有人都同意这个协议的设计,难。
文档化内容,不同标准化组织都有所不同。一般应该包括
- Introduction。协议的目的、领域、环境、前提。
- The communication model。参与方、关系、角色、泛化描述通信流。
- Communication steps or procedures。每个阶段的描述、通信过程。
- Message description。语义语法。
- Sequence of commands and replies。通信规则的详尽描述,包含state diagrams,sequence diagrams,以及通信过程的详尽解释。