Coding沙龙之协议状态机实现

    一个协议,常常伴随几个,甚至十几个状态机,如何有效实现这些协议状态机是完成协议开发的基础;且协议状态机往往比较复杂,是协议的核心部分,初期实现不好,后期维护成本非常高,且容易修改引入,所以如何实现一个高效的状态机尤为重要。

一、状态机分析、设计

    可以从以下4个方面进行:

    1、各个状态的含义:一般分为初始态、接入态、正常态、终结态,802.3、802.11等标准上千个协议,而协议状态机也是大同小异,均可以应用这四个状态进行套接,例如我们最熟悉的TCP协议三次握手。

    2、输入条件:除初始态外,各个状态均是由其他状态加上一定的输入条件切换而来。我们设计的状态机输入条件不易过多,可以参考标准协议状态机的输入条件设计,标准协议状态机的输入条件一般很简单,均不超过3个。如果设计的状态机有较多的输入条件,则状态机将变得复杂,状态切换不稳定,程序运行异常情况较多,后期维护成本非常高,所以但我们发现我们的状态机输入条件较多时(有的是后期修改bug临时添加的),则需要重新审视我们的状态机是否合理了,是否是因为修改bug采用了不合理的方案,或者需要将这个庞大的状态机进一步拆分。

    3、输出结果:同输入条件,较多的输出同样导致程序复杂,控制输出结果不超过3个为宜。

    4、状态切换:当前状态 + 输入条件 = 下一次状态 + 输出结果;状态切换不易太多,例如4个状态,最糟糕的是两两切换,可能的切换路径达到6次,此时我们的设计尽可能减少切换次数,降低状态机复杂度。

二、状态机编码实现

    成功完成状态机分析、设计后,如何高效完成状态机编码。不建议采用switch case、if esle来实现,这样将导致成功设计的状态机程序复杂,可读性、可维护性较低,即不满足编程的SMART原则。

    建议采用状态机驱动表机制,模型如下:    

    1、首先定义各个状态的处理函数指针:

       typedef void (*fsmProc)(int *, char *)        /* 状态机核心处理函数指针 */

如果状态机处理流程较复杂,还可以增加进入该状态的预处理和退出该状态的后处理

       typedef void (*fsmPrevProc)(int *, char *)     /* 进入状态预处理函数指针 */
       typedef void (*fsmAftProc)(int *, char *)   /* 退出状态后处理函数指针 */

     2、定义状态机驱动表元素

         typedef struct fsmproc{

               fsmStt;

             fsmProc;

             fsmPrevProc;

             fsmAftProc

         }FSM_PROC

     3、定义状态机驱动表

         FSM_PROC fsmProcTbl[4] = {

{ fsmStt1, fsmStt1Proc, NULL, NULL },

{ fsmStt2, fsmStt2Proc, fsmStt2PrevProc, fsmStt2AftProc }, 
{ fsmStt3, fsmStt3Proc, fsmStt3PrevProc, fsmStt3AftProc }, 
{ fsmStt4, fsmStt4Proc, NULL, NULL }, 

         }

        部分较简单状态,例如初始态、终结态等,不需要预处理,后处理流程,可以设置成NULL

     4、处理

        状态机对外只需要提供一个fsmEntry接口,在需要触发状态切换的流程中调用该接口,在fsmEntry中调用对应接口即可:

        if (fsmPrecTbl[fsmStt].fsmPrevProc)

        {

                  ret |= fsmProcTbl[fsmStt].fsmPrevProc(a,  b);

         }


后记:再简单的程序都有出现bug的可能,不用说核心状态机处理流程,所以说在状态机增加可维护性流程非常重要。

      在fsmEntry状态机中增加FSM_MTB,记录状态机运行轨迹,包括状态机状态、输入条件、输出结果等相关变量,可以方便出现问题时现场快速查询,快速定位。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值