模式名称
- SAD, Simple API for Datagram
意图
- 分离网络报文的解析和处理, 使解析代码和处理代码不再耦合在一起, 便于扩展. 类似SAX(Simple API for XML)将XML文档的解析和处理分离到不同的单元中
动机
在网络通信软件的开发中, 经常要处理网络上接收到的各种数据报文. 而收到某种报文后, 需要进行的处理逻辑上可能不止一件事情. 处理过程中会用到报文中的数据, 因此需要对报文进行解析. 而报文的结构通常存在动态部分, 而在C语言中, 无法定义一个数据结构可以直接将报文映射到该结构. 参见<<Navigator Pattern: 导航者模式>>
缺乏考虑的做法通常会把解析和处理放在一起, 一个大函数, 用局部变量甚至全局变量来保存解析出来的数据, 并对其进行各种处理. 这样做的问题是:
- 难以扩展: 当需要增加新的处理时, 需要在解析过程中多个地方插入处理代码
- 难以理解: 不同的处理代码混在一起, 和报文解析的逻辑也混在一起, 难以看清楚真正做了什么事
- 容易出错: 不同的处理共享解析出来的数据, 容易互相影响, 引入错误
另外一种常见的做法是每种不同的处理单独去解析自己需要的内容. 这种方式相对内聚, 但需要解析多遍报文结构, 解析代码也有重复
我们需要更好的设计.
方案
SAX以事件驱动的方式分离了XML文档的解析和处理. 我们可以借鉴. 报文有内部结构, 我们可以使用Navigator模式遍历其内部结构, 并在每一个独立的净荷开始和结束时触发回调, 而对报文内容的各种处理可以以回调函数的形式注册到解析过程中, 为每种处理编写单独的回调函数.
例如, 对于Navigator模式中定义的报文结构, 可以定义如下的API:
typedef void (*MessageHandler)(Message*);
typedef void (*TopLevelPayloadHandler)(TopLevelPayload*);
typedef void (*SecondLevelPayloadHandler)(SecondLevelPayload*);
typedef struct Handler {
MessageHandler start_handle_message;
MessageHandler end_handle_message;
TopLevelPayloadHandler start_handle_toplevel_payload;
TopLevelPayloadHandler end_handle_toplevel_payload;
SecondLevelPayloadHandler start_handle_secondlevel_payload;
SecondLevelPayloadHandler end_handle_secondlevel_payload;
} Handler;
void parse(Message* message, Handler* handlers, int handler_count) {
for(int i=0; i<handler_count; i++) {
handlers[i]->start_handle_message(message);
}
//遍历Message内部嵌套的payload, 并调用对应的handler, 比如:
//handlers[i]->start_handle_toplevel_payload(toplevel_payload_pointer);
//handlers[i]->end_handle_toplevel_payload(toplevel_payload_pointer);
for(int i=0; i<handler_count; i++) {
handlers[i]->end_handle_message(message);
}
}
而每种不同的处理, 只需提供自己的handler即可. 比如可以有打印报文内容的handler, 有根据报文操作硬件的handler, 有持久化报文数据的handler等:
Handler handlers[3] = {
DataPrinter,
HardwareManipulator,
DataPersister};
parse(message, handlers, sizeof(handlers)/sizeof(handlers[0]));
效果
- 报文解析和报文处理的代码彻底分开, 不再纠缠在一起
- 可以很容易的扩展新的报文处理逻辑
- 报文只需解析一遍
- 其约束在于不同的handler之间不应该有依赖
相关模式
- SAX是处理XML的一种类似的模式, 但其最初的出发点是源于DOM的性能太差, 不过它也有分离解析和处理的效果
- Visitor模式用于在不改变层次结构的情况下增加对这个层次结构的处理, 并且自动分发正确的处理到正确的节点. 它客观上也分离了数据的解析和对数据的处理.
分享到:
相关推荐
TCPIP协议原理教学课件:Chapter 9 User Datagram Protocol(UDP).ppt
udpSocket->readDatagram(datagram.data(),datagram.size());/ QString str=datagram.data(); udp_ui->TextEdit->insertPlainText(str.append(' ').toUpper()); ,对方发送停止,仍有空报文出现
application that accepts any of the format versions allocates a buffer large enough for the largest possible datagram from any of the format versions and then uses the header to determine how to ...
routing protocol for wireless datagram networks that uses the po- sitions of routers and a packet's destination to make packet for- warding decisions. GPSR makes greedy forwarding decisions us- ing ...
application scripts to make the same API calls to the network protocol stacks that real applications make, causing the protocol stacks to perform the same work involved in sending and receiving data ...
* raw/native API for enhanced performance * Optional Berkeley-like socket API * TLS: optional layered TCP ("altcp") for nearly transparent TLS for any TCP-based protocol (ported to mbedTLS) (see ...
$ factory -> createClient ( 'localhost:1234' )-> then ( function ( React \ Datagram \ Socket $ client ) { $ client -> send ( 'first' ); $ client -> on ( 'message' , function ( $ message , $ serverAd
它需要一个运行 (或 Mac 上的 boot2docker)的主机、一个查询存储数据库(Datagram 容器或其他数据库上的 SQLite 文件),以及对数据库的只读访问来运行查询。用法Datagram 构建为容器,可以在任何支持主机上运行...
韩国DATAGRAM无线网卡驱动DUWR-5400BG
* raw/native API for enhanced performance * Optional Berkeley-like socket API * TLS: optional layered TCP ("altcp") for nearly transparent TLS for any TCP-based protocol (ported to mbedTLS) (see ...
PEP 526: Syntax for variable annotations PEP 515: Underscores in Numeric Literals PEP 525: Asynchronous Generators PEP 530: Asynchronous Comprehensions PEP 487: Simpler customization of class ...
这些 API适用于TCP/IP协议簇,支持 面向连接Stream (TCP) 及 面向无连接Datagram (UDP) Socket。
VMware VMCI Driver for Linux v2.13.6.
UDP(User Datagram Protocol)是一种无连接的传输层协议
UDP(User Datagram Protocol)是一种在计算机网络中常用的传输层协议,它提供了一种简单的、无连接的数据传输服务。与TCP不同,UDP不提供可靠性、顺序传输和拥塞控制等功能,因此在某些情况下,UDP比TCP更适合。 ...
VMware VMCI Driver for Linux v2.13.6.
nodejs api 离线 网页版 Table of Contents About these Docs Synopsis Globals STDIO Timers Modules C/C++ Addons Process Utilities Events Domain Buffer Stream Crypto TLS/SSL String ...
Bruce runs on each individual host that communicates with Kafka, receiving messages from local clients over a UNIX domain datagram socket. Clients write messages to Bruce's socket in a simple binary ...
This User Datagram Protocol (UDP) is defined to make available a datagram mode of packet-switched computer communication in the environment of an interconnected set of computer networks. This protocol...