原創(chuàng)  使用信元流(TLVStream)規(guī)范、簡化模塊(C/C++)間交互 收藏

            問題描述:
            在軟件開發(fā)過程中,一般會對復雜的現(xiàn)實世界進行抽象,并且采用分而治之的策略,將大系統(tǒng)分解為子系統(tǒng),將子系統(tǒng)分解為一個個的模塊。模塊間的通信一般采用函數(shù)調(diào)用的方式,這樣會產(chǎn)生一些問題:
             1. 模塊間的接口增多會導致模塊間緊密耦合,不利于模塊的重用、調(diào)試、維護。
             2. 接口函數(shù)參數(shù)會很復雜,容易出現(xiàn)很龐大,功能面面俱到的結構體。
             3. 不利于擴展,新增功能要新增接口函數(shù),或者修改接口參數(shù)。


          信元流的定義
            信元流是一種處理數(shù)據(jù)的方式。它對現(xiàn)實世界的數(shù)據(jù)進行抽象,形成一個一個的信元,然后由這些信元以一定的方式組合起來,形成信元流,來傳遞數(shù)據(jù)。下面信元流的實現(xiàn)。
            信元的實現(xiàn)
            信元由三部分組成,分別是信元標識(Tag),信元長度(Length),信元值(Value),即TLV格式。下面是一個信元的c定義:   
            typedef struct __ELEMENT_ST

               {

                    ELE_TAG tag;

                    ELE_LEN len;

                    ELE_VALUE value;

               }ELEMENT_ST;

            信元流的實現(xiàn):
            信元流分為兩部分,信元流頭部(head)和體部(body)。head部分用于記錄信元流的整體描述,比如,信元流的起始模塊,目的模塊,以及信元流的消息類型等等。當然,也可以根據(jù)需要自己進行擴展。body部分包括信元流中信元的總大小,即ELE_MSG_BODY中body的長度。

                  typedef struct __ELEMENT_STREAM_ST
                  {
                      MOD_ID src_mod;
                      MOD_ID des_mod;
                      ELE_MSG_TYPE type;
                      ELE_MSG_BODY body;
                  }ELEMENT_STREAM_ST;
                  typedef struct __ELE_MSG_BODY
                  {
                      ELE_MSG_LEN len;
                      char body[MAX_ELE_MSG_BODY_LEN];
                  } ELE_MSG_BODY;

            構造信元流
            定義好結構體后,下面定義兩個函數(shù),分別向信元體中添加信元和刪除信元。
             //pbody信元體的指針。這里沒有使用信元流的指針是為了讓函數(shù)的重用性更好,用戶可以自己定義信元流。
                  //tag:添加信元的TAG值,len:添加信元的長度。pvale:添加信元的值。
                  int AddElementToStreamBody(ELE_MSG_BODY *pbody, ELE_TAG tag, ELE_LEN len, void *pvalue);
                  //pbody信元體的指針。 //tag:獲取信元的TAG值,buf_len:pbuf的長度。pbuf:目標緩沖區(qū),要把信元VALUE的值寫入吃緩沖區(qū)。
                  int GetElementFromStreamBody(ELE_MSG_BODY *pbody, ELE_TAG tag, int buf_len, void *pbuf);
            信元流的body是一個緩沖區(qū),信元在里面順序排列。信元在body中順序不影響它的獲取。添加和獲取的方法比較簡單,不再贅述。


            一個信元流的實例
            下面來舉一個具體的例子來介紹一下信元流的使用,以及它的優(yōu)點。
            假如由兩個模塊A和B。A模塊負責處理業(yè)務邏輯,B模塊負責處理呼叫控制。A調(diào)用B的一個接口發(fā)起呼叫,接口如下。
                  typedef struct __MAKE_CALL_ST
                  {
                      char caller_num[MAX_NUM_LEN];//主叫號碼
                      char called_num[MAX_NUM_LEN];//被叫號碼
                  }MAKE_CALL_ST;
                  int MakeCall(MAKE_CALL_ST *pcall_info);

            后面需求有更改,某些情況下藥攜帶主叫的callid信息。結構體會變成:
              typedef struct __MAKE_CALL_ST
              {
                  char caller_num[MAX_NUM_LEN];//主叫號碼
                  char called_num[MAX_NUM_LEN];//被叫號碼
                  CALL_ID caller_callid;
              }MAKE_CALL_ST;
            某些情況下又需要攜帶主叫的SDP信息,結構體會變成:
              typedef struct __MAKE_CALL_ST
              {
                  char caller_num[MAX_NUM_LEN];//主叫號碼
                  char called_num[MAX_NUM_LEN];//被叫號碼
                  CALL_ID caller_callid;
                  SDP_INFO call_sdp;
              }MAKE_CALL_ST;
            隨著需求的增加,這個結構體會越來越大,并且,其中的成員在某些情況下要使用,某些情況下又不使用,造成模塊間的冗余數(shù)據(jù)。
            當然,你也可以采用其他的方法,比如,再多定義幾個接口和結構體。但是這樣的話接口和結構體的數(shù)量會呈爆炸式的增長。
            使用信元流可以很好的解決這個問題。把號碼,callid,sdp等全部定義成信元,需要的時候塞進去,不需要的話就不添加。另外還有一個好處就是,一個模塊可以對外只公布一個接口,來收取信元流,然后在根據(jù)信元流的類型進行分別處理。這樣,一個模塊對外就只有一個接口了,模塊間的耦合性會降低。


          一點改進
            上面定義的信元流的格式在實際使用的過程中還是碰到了一些問題,最突出的就是,信元流的大小是固定死的。這種情況下,如果信元信息很小,會導致空間浪費,效率降低;如果信元信息很多,信元流的空間又不夠。

            可以對上面的這種方案進行一下優(yōu)化,把信元的定義更改為:

            typedef struct __ELEMENT_ST

               {

                    ELE_TAG tag;

                    ELE_LEN len;

                    ELE_VALUE value;

                    ELEMENT_ST  *pnext_ele;//下一個信元流

               }ELEMENT_ST;

            將信元流的定義更改為:

                  typedef struct __ELEMENT_STREAM_ST
                  {
                      MOD_ID src_mod;
                      MOD_ID des_mod;
                      ELE_MSG_TYPE type;
                      ELEMENT_ST  *pfirst_ele;//第一個信元流
                  }ELEMENT_STREAM_ST;

            將信元流和信元更改為動態(tài)申請的內(nèi)存。這樣既可以提高效率,有沒有了大小的限制。

            需要增加兩個接口,來申請和釋放信元流。

            唯一不好的地方時,動態(tài)申請的內(nèi)存需要程序員記得釋放,否則會內(nèi)存泄露。不過還有一個方法,即增加一個申請信元流的函數(shù),如下
                  ELEMENT_STREAM_ST *GetEleStream()
                  {
                      static     ELEMENT_STREAM_ST *pstream = NULL;
                      if (NULL != pstream)
                      {
                          FreeEleStream(pstream);   
                          pstream = NULL;
                      }
                      pstream = AllocteEleStream();
                      return pstream;
                  }

            這樣的話,通過函數(shù)GetEleStream獲取的信元流,只在函數(shù)范圍內(nèi)有效,退出函數(shù)后,立即無效。


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           

          posts - 19, comments - 0, trackbacks - 0, articles - 0

          Copyright © 常高偉

          主站蜘蛛池模板: 陈巴尔虎旗| 高邑县| 贺州市| 白山市| 文水县| 工布江达县| 乌兰察布市| 汉寿县| 子洲县| 陕西省| 张掖市| 额尔古纳市| 江达县| 宁陕县| 绥阳县| 望谟县| 奉新县| 寿宁县| 东乡县| 财经| 绥阳县| 溆浦县| 丹东市| 泾川县| 诏安县| 定州市| 株洲县| 和顺县| 通城县| 内丘县| 顺昌县| 通江县| 竹北市| 扬中市| 石首市| 郯城县| 澄迈县| 黔江区| 贞丰县| 巧家县| 台东县|