`
chelsea
  • 浏览: 118221 次
  • 来自: ...
社区版块
存档分类
最新评论

SAD Pattern: Simple API for Datagram

 
阅读更多

模式名称

  • 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

    本教学课件专注于讲解传输层中的User Datagram Protocol(UDP),即用户数据报协议。 UDP是无连接的传输层协议,与面向连接的Transmission Control Protocol(TCP)形成鲜明对比。TCP提供了一种可靠的数据流服务,...

    vmci_datagram.rar_V2

    总之,"VMware VMCI Driver for Linux v2.13.6" 提供了一个高效的虚拟化环境中通信的框架,`vmci_datagram.c` 和 `vmci_datagram.h` 文件则具体实现了这一功能,为开发者提供了与 VMCI 数据报通信的接口和实现。...

    基于实时通信API的视频会议系统

    5. **安全性**:RTC API支持DTLS(Datagram Transport Layer Security)和SRTP(Secure Real-time Transport Protocol)来加密通信,保护用户隐私和数据安全。 6. **多设备兼容**:考虑到跨平台的需求,RTC API应能...

    前端项目-simple-peer.zip

    1. **简洁的API**:simple-peer提供了简单的JavaScript API,使得开发者可以快速上手,比如通过`peer.connect()`建立连接,`peer.addStream()`添加本地媒体流,`peer.on('data')`监听数据通道消息。 2. **自动处理...

    vmci_datagram.rar_V2 _vmci

    在这个压缩包中,我们有两个核心文件:`vmci_datagram.c` 和 `vmci_datagram.h`,它们分别包含了 VMCI_Datagram 的实现代码和头文件定义。 `vmci_datagram.c` 文件是 C 语言编写的源代码,它实现了 VMCI_Datagram ...

    QT5 UDP通讯之接收

    udpSocket.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); // 处理接收到的datagram数据 processReceivedDatagram(datagram, sender, senderPort); } } ``` `...

    webrtc API 中文翻译

    此外,了解STUN(Session Traversal Utilities for NAT)和TURN(Traversal Using Relays around NAT)服务器的作用也很重要,它们帮助穿越NAT障碍,实现全网通信。 通过中文翻译的WebRTC API文档,开发者可以更...

    Rtsp Simple Server源码go语言

    1. **UDP(User Datagram Protocol)**:是一种无连接的传输层协议,适合于对实时性要求较高的应用场景,如在线直播、VoIP等。但由于其无连接特性,不保证数据包的顺序和可靠性,可能会有丢包现象。 2. **TCP...

    UDP组播双向通信,socket编程

    qDebug() &lt;&lt; "Received datagram: " &lt;&lt; datagram.data(); ``` 为了支持IP和端口的修改,可以在程序中添加相应的界面元素(如文本框或下拉框),允许用户输入新的IP和端口,然后调用`udpSocket-&gt;disconnectFromHost...

    NetFlow Export Datagram Format

    NetFlow是网络流量分析工具,由思科公司开发,用于收集网络中数据包的统计信息,帮助网络管理员了解流量模式和网络使用情况。NetFlow导出的数据报格式是用于在路由器和交换机上收集和导出网络流量数据的标准格式,...

    linux_网络编程API

    UDP(User Datagram Protocol)是一种无连接的协议,它不保证数据的顺序或可靠性,但提供了较低的延迟。在Linux中,主要涉及以下函数: - `sendto()`:用于向指定的UDP套接字发送数据到目的地。函数原型如下: ...

    Nodejs-API-中文文档.pdf

    Node.js API 中文文档 Node.js 是一个基于 Chrome V8 JavaScript 引擎的 JavaScript 运行环境,它提供了大量的 API 来实现各种功能。下面是 Node.js API 中文文档的摘要信息: Globals * global 对象:提供了...

    Java入门笔记.doc

    本文档旨在介绍Java中的Socket编程基础知识,特别是关于数据报Socket(Datagram Socket)的相关概念和技术细节。 #### 二、Java Socket概述 Java通过Socket来完成所有网络底层的通信。Socket可以理解为一种通道,...

    Windows Sockets API 介绍.pdf

    ### Windows Sockets API 介绍 #### 一、概述 Windows Sockets API(简称Winsock)是一种为Windows操作系统设计的网络编程接口,它基于Berkeley Sockets API并进行了扩展,以支持Windows特有的消息驱动机制。...

    owt-server-master.zip

    - **安全特性**:通过 DTLS(Datagram Transport Layer Security)和 SRTP(Secure Real-time Transport Protocol)提供安全的媒体传输。 - **API 接口**:提供 RESTful API 和 WebSocket API,便于集成到其他系统和...

    VIDEOCAPTURE.tar.gz_linux arm_udp 摄像头_video for linux_网络摄像头

    2. **Linux下的摄像头数据采集**:这可能涉及到Linux内核的Video for Linux (V4L)接口,V4L是一个API,允许用户空间程序与各种类型的视频设备(如摄像头)进行交互,获取和处理视频流。 3. **JPEG压缩**:JPEG是一种...

    韩国DATAGRAM无线网卡驱动DUWR-5400BG.rar

    标题中的“韩国DATAGRAM无线网卡驱动DUWR-5400BG.rar”表明这是一个针对韩国DATAGRAM公司生产的DUWR-5400BG无线网卡的驱动程序压缩包。驱动程序是计算机硬件与操作系统之间的重要桥梁,它允许操作系统识别并控制硬件...

    BSD套接字API资料锦集

    **BSD套接字API**是计算机网络编程中的一个重要概念,源于Berkeley Software Distribution(BSD)系统,后来被广泛应用于各种操作系统,包括Unix、Linux以及Windows等。它为开发者提供了一组标准化的接口,用于实现...

Global site tag (gtag.js) - Google Analytics