posts - 5, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          2012年7月19日

          SQL 不同于與其他編程語(yǔ)言的最明顯特征是處理代碼的順序。在大數(shù)編程語(yǔ)言中,代碼按編碼順序被處理,但是在SQL語(yǔ)言中,第一個(gè)被處理的子句是FROM子句,盡管SELECT語(yǔ)句第一個(gè)出現(xiàn),但是幾乎總是最后被處理。

                每個(gè)步驟都會(huì)產(chǎn)生一個(gè)虛擬表,該虛擬表被用作下一個(gè)步驟的輸入。這些虛擬表對(duì)調(diào)用者(客戶端應(yīng)用程序或者外部查詢)不可用。只是最后一步生成的表才會(huì)返回 給調(diào)用者。如果沒(méi)有在查詢中指定某一子句,將跳過(guò)相應(yīng)的步驟。下面是對(duì)應(yīng)用于SQL server 2000和SQL Server 2005的各個(gè)邏輯步驟的簡(jiǎn)單描述。


          復(fù)制代碼
          (8)SELECT (9)DISTINCT  (11)<Top Num> <select list>
          (
          1)FROM [left_table]
          (
          3)<join_type> JOIN <right_table>
          (
          2)ON <join_condition>
          (
          4)WHERE <where_condition>
          (
          5)GROUP BY <group_by_list>
          (
          6)WITH <CUBE | RollUP>
          (
          7)HAVING <having_condition>
          (
          10)ORDER BY <order_by_list>
          復(fù)制代碼

          邏輯查詢處理階段簡(jiǎn)介

          1. FROM:對(duì)FROM子句中的前兩個(gè)表執(zhí)行笛卡爾積(Cartesian product)(交叉聯(lián)接),生成虛擬表VT1
          2. ON:對(duì)VT1應(yīng)用ON篩選器。只有那些使<join_condition>為真的行才被插入VT2。
          3. OUTER(JOIN):如 果指定了OUTER JOIN(相對(duì)于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部聯(lián)接把左表標(biāo)記為保留表,右外部聯(lián)接把右表標(biāo)記為保留表,完全外部聯(lián)接把兩個(gè)表都標(biāo)記為保留表)中未找到匹配的行將作為外部行添加到 VT2,生成VT3.如果FROM子句包含兩個(gè)以上的表,則對(duì)上一個(gè)聯(lián)接生成的結(jié)果表和下一個(gè)表重復(fù)執(zhí)行步驟1到步驟3,直到處理完所有的表為止。
          4. WHERE:對(duì)VT3應(yīng)用WHERE篩選器。只有使<where_condition>為true的行才被插入VT4.
          5. GROUP BY:按GROUP BY子句中的列列表對(duì)VT4中的行分組,生成VT5.
          6. CUBE|ROLLUP:把超組(Suppergroups)插入VT5,生成VT6.
          7. HAVING:對(duì)VT6應(yīng)用HAVING篩選器。只有使<having_condition>為true的組才會(huì)被插入VT7.
          8. SELECT:處理SELECT列表,產(chǎn)生VT8.
          9. DISTINCT:將重復(fù)的行從VT8中移除,產(chǎn)生VT9.
          10. ORDER BY:將VT9中的行按ORDER BY 子句中的列列表排序,生成游標(biāo)(VC10).
          11. TOP:從VC10的開(kāi)始處選擇指定數(shù)量或比例的行,生成表VT11,并返回調(diào)用者。

          注:步驟10,按ORDER BY子句中的列列表排序上步返回的行,返回游標(biāo)VC10.這一步是第一步也是唯一一步可以使用SELECT列表中的列別名的步驟。這一步不同于其它步驟的 是,它不返回有效的表,而是返回一個(gè)游標(biāo)。SQL是基于集合理論的。集合不會(huì)預(yù)先對(duì)它的行排序,它只是成員的邏輯集合,成員的順序無(wú)關(guān)緊要。對(duì)表進(jìn)行排序 的查詢可以返回一個(gè)對(duì)象,包含按特定物理順序組織的行。ANSI把這種對(duì)象稱為游標(biāo)。理解這一步是正確理解SQL的基礎(chǔ)。

          因?yàn)檫@一步不返回表(而是返回游標(biāo)),使用了ORDER BY子句的查詢不能用作表表達(dá)式。表表達(dá)式包括:視圖、內(nèi)聯(lián)表值函數(shù)、子查詢、派生表和共用表達(dá)式。它的結(jié)果必須返回給期望得到物理記錄的客戶端應(yīng)用程序。例如,下面的派生表查詢無(wú)效,并產(chǎn)生一個(gè)錯(cuò)誤:

          select * 
          from(select orderid,customerid from orders order by orderid)
          as d

          下面的視圖也會(huì)產(chǎn)生錯(cuò)誤

          create view my_view
          as
          select
          *
          from orders
          order by orderid

                在SQL中,表表達(dá)式中不允許使用帶有ORDER BY子句的查詢,而在T—SQL中卻有一個(gè)例外(應(yīng)用TOP選項(xiàng))。

                所以要記住,不要為表中的行假設(shè)任何特定的順序。換句話說(shuō),除非你確定要有序行,否則不要指定ORDER BY 子句。排序是需要成本的,SQL Server需要執(zhí)行有序索引掃描或使用排序運(yùn)行符。

          posted @ 2012-08-10 15:58 火炎炎 閱讀(171) | 評(píng)論 (0)編輯 收藏

          CMPP2.0開(kāi)發(fā)

          一、CMPP協(xié)議簡(jiǎn)介
          中國(guó)移動(dòng)通信互聯(lián)網(wǎng)短信網(wǎng)關(guān)接口協(xié)議(China Mobile Peer to Peer CMPP),是中國(guó)移動(dòng)夢(mèng)網(wǎng)內(nèi)部各SMS參與節(jié)點(diǎn)相互交換SMS的官方協(xié)議。作為夢(mèng)網(wǎng)的參與方,移動(dòng)夢(mèng)網(wǎng)的增值服務(wù)商(Service Provider SP )要按照此協(xié)議規(guī)范實(shí)現(xiàn)SP的部分,才可以將自己的短信通過(guò)移動(dòng)的GSM網(wǎng)絡(luò)的數(shù)據(jù)通道傳輸?shù)阶罱K手機(jī)用戶上。
          實(shí)際上,協(xié)議規(guī)范了3個(gè)方面的內(nèi)容:
          。SP與移動(dòng)的互聯(lián)網(wǎng)短信網(wǎng)關(guān)(Internet Short Message Gateway,ISMG)之間的接口協(xié)議
          。ISMG之間的接口協(xié)議(譬如移動(dòng)各省、市之間的短信息交換通過(guò)ISMG之間進(jìn)行)
          。ISMG與匯接網(wǎng)關(guān)(Gateway Name Server GNS,類似互聯(lián)網(wǎng)上的DNS服務(wù)器)之間的接口協(xié)議,譬如跨省之類的短信需要GNS的幫助指出當(dāng)前ISMG該如何傳遞短信。
          其中,后二方面屬于移動(dòng)短信息系統(tǒng)內(nèi)部實(shí)現(xiàn),對(duì)于SP來(lái)講大概可以“透明”來(lái)看待,只要實(shí)現(xiàn)了SP同ISMG的正確交互,就可以實(shí)現(xiàn)接入移動(dòng)夢(mèng)網(wǎng)短信系統(tǒng)。我們關(guān)心的只是SP端的開(kāi)發(fā)細(xì)節(jié)。
          二、CMPP交互模式
          從手機(jī)用戶角度講,按短信的發(fā)起/接收路徑來(lái)講,有兩個(gè)叫法:
          MT(Short Message Mobile Terminated, SMMT),短信接收,短信從SP發(fā)送到手機(jī)用戶。
          MO (Short Message Mobile Originate,SMMO),短信發(fā)送,短信從手機(jī)用戶端發(fā)送到目標(biāo)SP。
          這兩類短信交互,從SP端來(lái)看,都是屬于Socket傳輸應(yīng)用,CMPP的協(xié)議是以TCP/IP協(xié)議作為底層承載協(xié)議的,屬于TCP/IP協(xié)議棧之上的應(yīng)用。
          SP同ISMG的交互連接分長(zhǎng)連接短連接。
          所謂短連接,就是一次連接,傳輸一個(gè)消息,然后等待回復(fù)后拆除連接,顯然,效率很低,所以,基本上不被考慮(實(shí)際應(yīng)用移動(dòng)也不允許SP采用短連接,只是不明白移動(dòng)為什么還要寫入文檔? ISMG間會(huì)需要?)
          所謂長(zhǎng)連接,就是SP建立同ISMG連接,然后不斷將數(shù)據(jù)包(一個(gè)個(gè)CMPP消息)發(fā)送到ISMG,此處發(fā)送不必等待某條消息的ISMG回應(yīng)消息返回,就接著發(fā)送下一個(gè)消息。同時(shí),等待ISMG返回信息或者等待ISMG發(fā)送給SP的消息。發(fā)送同接收消息不是一定要同步的,實(shí)際采用異步(同時(shí)也時(shí)雙工)模式。從效率上,顯然,必須全雙工的異步模式才能夠滿足實(shí)際應(yīng)用需求。
          如下圖(摘自CMPP2.0官方文檔)所示,演示了長(zhǎng)連接模式數(shù)據(jù)傳輸過(guò)程:
           
           
           
           
           
           
           

          三、SP端開(kāi)發(fā)
          1.         消息分類
          首先,圖中的CMPP消息有很多種,SP同ISMG之間交流這些消息。大體上這些消息發(fā)出后,對(duì)方往往需要回復(fù)一個(gè)應(yīng)答(RESP)類消息。注意,這些消息大多具有方向性,也就是說(shuō)只能夠從一端到另一端,而不可反方向進(jìn)行,有些(少數(shù))則可兩端都能夠發(fā)出。以下信息主要來(lái)源于移動(dòng)的文檔,但針對(duì)大家易混淆或源文檔解釋不夠詳細(xì)做了明確和補(bǔ)充。具體見(jiàn)下表:
                 消息名
          傳遞方向
          解釋說(shuō)明
          CMPP­_CONNECT
          SP---àISMG
          CMPP_CONNECT操作的目的是SP向ISMG注冊(cè)作為一個(gè)合法SP身份,此消息需要向ISMG發(fā)出驗(yàn)證信息,驗(yàn)證方式采用md5加密密碼方式,若注冊(cè)成功后即建立了應(yīng)用層的連接(否則ISMG會(huì)立即斷開(kāi)Socket),此后SP可以通過(guò)此ISMG接收和發(fā)送短信。
          ISMG以CMPP_CONNECT_RESP消息響應(yīng)SP的請(qǐng)求。具體的算法實(shí)現(xiàn)參考CMPP2.0文檔和本文附件代碼。
          CMPP_CONNECT_RESP
          SPß---ISMG
          ISMG對(duì)CMPP_CONNECT消息的回復(fù)(無(wú)論是否驗(yàn)證成功);如果未通過(guò),會(huì)在消息中包含參考信息,但I(xiàn)SMG會(huì)立即斷開(kāi)連接。
          CMPP­_ACTIVE_TEST
          SPßàISMG
          這個(gè)消息通信雙方都可以發(fā)出,目的是在沒(méi)有其他消息發(fā)送時(shí),保持雙方的通信鏈路的連接,避免系統(tǒng)認(rèn)為通信通道已經(jīng)關(guān)閉。每一個(gè)收到此消息的實(shí)體應(yīng)當(dāng)返回CMPP_ACTIVE_TEST_RESP消息,以“禮節(jié)性”表示自己的還在通信,維持?jǐn)?shù)據(jù)連接有效性。
          不過(guò),據(jù)網(wǎng)友交流,有些廠家實(shí)現(xiàn)的ISMG,僅僅靠自己發(fā)出此消息等待SP回答CMPP_ACTIVE_TEST_RESP來(lái)確定數(shù)據(jù)鏈路的有效性,而忽略SP的CMPP_ACTIVE_TEST消息(有些霸道吧?)這個(gè)值得注意,不要僅僅實(shí)現(xiàn)發(fā)送而不響應(yīng)此消息,避免數(shù)據(jù)連接失效。
          CMPP_ACTIVE_TEST_RESP
          SPßàISMG
          對(duì)通信的另一端的CMPP_ACTIVE_TEST消息的回復(fù)。作用參考CMPP_ACTIVE_TEST的解釋。
          CMPP­_SUBMIT
          SP---àISMG
          在正確建立了數(shù)據(jù)連接后,SP向ISMG發(fā)送一個(gè)SMS數(shù)據(jù)包。本消息需要仔細(xì)研究。接收到此消息后,ISMG需要以CMPP_SUBMIT_RESP消息作為回答。如果在一定時(shí)間時(shí)間內(nèi)(移動(dòng)給出的參考值60秒)內(nèi)未得到消息回應(yīng),那么SP需要重新發(fā)送此數(shù)據(jù)包,以確保消息得到投遞。如果重發(fā)達(dá)到3次后仍然得不到回應(yīng),SP端應(yīng)該考慮可能ISMG已經(jīng)失效,應(yīng)當(dāng)停止發(fā)送此短消息。
          CMPP­_SUBMIT_RESP
          SPß---ISMG
          該消息由ISMG發(fā)送給SP,同時(shí)返回一個(gè)“收條”(源CMPP_SUBMIT消息的ISMG端的標(biāo)示MSGID)給SP,表示“我ISMG已經(jīng)確認(rèn)收到你這條消息了”。收到此消息后,SP需要保留此“收條”,因?yàn)楹竺鍵SMG會(huì)最終報(bào)告本消息是否正確發(fā)送到用戶手機(jī)。那個(gè)報(bào)告就是以此消息的“收條”作為確認(rèn)那一條消息的。
          CMPP_QUERY
          SP---àISMG
          這個(gè)查詢不是查詢單條消息的,是查詢SP發(fā)送給ISMG的短信的業(yè)務(wù)情況??梢圆榭傆?jì)數(shù),還可以分類查詢。(基本就是發(fā)起對(duì)移動(dòng)sms業(yè)務(wù)數(shù)據(jù)庫(kù)的查詢統(tǒng)計(jì))
          CMPP_QUERY_RESP
          SPß---ISMG
          ISMG將查詢的數(shù)據(jù)返回給SP。
          CMPP_CANCEL
          SP---àISMG
          SP發(fā)起的取消某條消息的命令消息,其中包含了之前已經(jīng)發(fā)送給ISMG消息的“收條”以便ISMG可以確定是那一條消息。如果消息已經(jīng)發(fā)送給用戶了,那么此消息/命令會(huì)無(wú)效,ISMG返回失敗。
          CMPP_CANCEL_RES
          SPß---ISMG
          ISMG返回的對(duì)CMPP_CANCEL的回復(fù),并告知是否刪除成功。
          CMPP_DELIVER
          SPß---ISMG
          當(dāng)有MO或者狀態(tài)報(bào)告時(shí),ISMG發(fā)送此消息。注意,此消息的數(shù)據(jù)可以是用戶手機(jī)發(fā)送給SP的消息,也可是對(duì)于之前SP發(fā)送到ISMG的短信的最終狀態(tài)的回復(fù),報(bào)告短信的最終狀態(tài)。
          CMPP_DELIVER_RESP
          SP---àISMG
          SP禮節(jié)性的回復(fù)告知收到CMPP_DELIVER消息。要指出SP報(bào)告的CMPP_DELIVER消息的MSGID,以便ISMG知道那一條消息SP已經(jīng)確認(rèn)收到。
          CMPP_TERMINAT
          SPßàISMG
          SP和ISMG都可以主動(dòng)發(fā)消息給對(duì)方,自己這端由于某種原因需要終止當(dāng)前的數(shù)據(jù)連接。終止后,要經(jīng)過(guò)重新Connection(驗(yàn)證)之后才可以(進(jìn)入事務(wù)階段)發(fā)送SMS數(shù)據(jù)消息。
          CMPP­_TERMINATE_RES
          SPßàISMG
          通知對(duì)方,本端已經(jīng)最好撤除連接的準(zhǔn)備。
                              
          2.         交互階段
          整個(gè)CMPP協(xié)議交互分為驗(yàn)證、事務(wù)兩個(gè)階段。驗(yàn)證階段,發(fā)送CMPP_CONNECTION消息進(jìn)行驗(yàn)證,通過(guò)驗(yàn)證后(必須要通過(guò)才)進(jìn)入CMPP事務(wù)階段,可以發(fā)送短信數(shù)據(jù)了。上表中的CMPP_CONNECTION以下的消息都屬于事務(wù)階段的消息。
           
          3.         消息數(shù)據(jù)結(jié)構(gòu)
          每一個(gè)消息包含 消息頭消息體兩個(gè)部分,頭固定長(zhǎng)度為12字節(jié),其他消息長(zhǎng)度各異,但是同一類型消息的長(zhǎng)度是固定的。所有消息的各個(gè)字段基本上僅有3種類型:Unsigned Integer (無(wú)符號(hào)整型)  、Integer(整型)、Octet String(字符串),每種類型具體長(zhǎng)度不定,網(wǎng)絡(luò)字節(jié)順序。
          1、  消息頭(3個(gè)Unsigned Integer字段組成):
          4字節(jié)的Total_Length (Unsigned Integer),包含了此消息的總計(jì)(包括了頭部分)長(zhǎng)度。
          4字節(jié)的Command_Id(Unsigned Integer),指明了此消息到底是什么消息,就是上表中消息的枚舉值。應(yīng)用程序根據(jù)此值確定本數(shù)據(jù)包到底是什么消息,從而可以按照確定的消息類型,解析余下的消息體。
          4字節(jié)的Sequence_Id(Unsigned Integer),指明了此數(shù)據(jù)包在發(fā)送此消息端的唯一編號(hào)。這個(gè)唯一編號(hào),實(shí)際上可以看作流水操作編號(hào)。因?yàn)榉治龅浇换ツJ轿覀兛吹?,SP發(fā)送數(shù)據(jù)到ISMG,不是每發(fā)送一個(gè)就停下來(lái)等待ISMG的回復(fù),而是“一下子”發(fā)送多個(gè)數(shù)據(jù)包過(guò)去,然后等待ISMG的回應(yīng)。然而,怎么知道回應(yīng)的消息是到底對(duì)應(yīng)之前發(fā)送過(guò)去的消息中的那一條呢?本字段就是解決此難題。SP按照編號(hào)發(fā)送消息過(guò)去,等待ISMG的回應(yīng)—一般情形下回應(yīng)消息數(shù)據(jù)結(jié)構(gòu)都有表明本消息回應(yīng)的是SP發(fā)出的哪一條消息,這個(gè)對(duì)應(yīng)就是依靠Sequence_Id。它并不要求一定要嚴(yán)格唯一,但是在給定的一段時(shí)間內(nèi),必須唯一(基本上只要SP發(fā)送過(guò)去的消息中沒(méi)有重復(fù)就行了)。如果是需要SP回答的消息,SP也必須將ISMG發(fā)送過(guò)來(lái)的消息的Sequence_Id填入相應(yīng)字段,表明這是某個(gè)消息的回應(yīng)。SP端和ISMG端Sequence_ID都沒(méi)有確定具體的算法。SP可以(但不推薦)采用數(shù)據(jù)庫(kù)的唯一Id作為此值。
           
          2、消息體。消息體長(zhǎng)度根據(jù)消息不同,長(zhǎng)度不一。其他的參考移動(dòng)的文檔《中國(guó)移動(dòng)通信互聯(lián)網(wǎng)短信網(wǎng)關(guān)接口協(xié)議(China Mobile Peer to Peer, CMPP)(V2.0)》,這里著重講講2個(gè)重要消息的消息體數(shù)據(jù)結(jié)構(gòu):
                 CMPP­_SUBMIT的消息體:
          字段名
          長(zhǎng)度(byte)
          類型
          描述
          Msg_Id
          8
          Unsigned Integer
          信息標(biāo)識(shí),應(yīng)該由SP側(cè)ISMG本身產(chǎn)生,本處填空,供ISMG傳輸時(shí)使用。SP提交時(shí)候應(yīng)當(dāng)留空。
          Pk_total
          1
          Unsigned Integer
          相同Msg_Id的信息總條數(shù),從1開(kāi)始。如果一條消息長(zhǎng)度超多一條短信,可能需要分解成多條消息,那么實(shí)際上這多條消息屬于一條完整消息,所以可以根據(jù)此給分解得到的多條短信進(jìn)行編號(hào),那么總計(jì)需要編成多少條短信,此處就填寫多少。
           
          Pk_number
          1
          Unsigned Integer
          相同Msg_Id的信息序號(hào),從1開(kāi)始。編號(hào)決定消息的相對(duì)位置。
          Registered_Delivery
          1
          Unsigned Integer
          是否要求返回狀態(tài)確認(rèn)報(bào)告:
          0:不需要
          1:需要
          2:產(chǎn)生SMC話單(該類型短信僅供網(wǎng)關(guān)計(jì)費(fèi)使用,不發(fā)送給目的終端)。
          一般情況下,都需要確認(rèn)報(bào)告。SMC話單也需要返回是否成功的報(bào)告。這條消息用于包月SMC時(shí),當(dāng)你發(fā)送消息給移動(dòng)的ISMG,移動(dòng)的計(jì)費(fèi)系統(tǒng)會(huì)一次性扣除用戶的信息費(fèi),但是此消息不會(huì)送到用戶手機(jī)。但是注意,有的ISMG廠商(很可能是移動(dòng)要求)實(shí)現(xiàn)此消息時(shí)候,如果你并沒(méi)有發(fā)送任何此包月類型的消息給用戶手機(jī),是不發(fā)生扣費(fèi)行為的。移動(dòng)會(huì)認(rèn)為這是屬于違規(guī)的“代收費(fèi)”行為,會(huì)影響同移動(dòng)的合作關(guān)系。
          Msg_level
          1
          Unsigned Integer
          信息級(jí)別,信息的優(yōu)先級(jí)。不過(guò)實(shí)際當(dāng)中,感覺(jué)ISMG端并沒(méi)有區(qū)分優(yōu)先級(jí)。
          Service_Id
          10
          Octet String
          業(yè)務(wù)類型,是數(shù)字、字母和符號(hào)的組合。這個(gè)表示業(yè)務(wù)的字符串可以給發(fā)出的短信分類。通過(guò)此字段大約可以知道每個(gè)服務(wù)項(xiàng)目的業(yè)務(wù)量,有利于統(tǒng)計(jì)和計(jì)費(fèi)以及結(jié)算。
          Fee_UserType
          1
          Unsigned Integer
          計(jì)費(fèi)用戶類型字段
          0:對(duì)目的終端MSISDN計(jì)費(fèi);
          1:對(duì)源終端MSISDN計(jì)費(fèi);
          2:對(duì)SP計(jì)費(fèi);
          3:表示本字段無(wú)效,對(duì)誰(shuí)計(jì)費(fèi)參見(jiàn)Fee_terminal_Id字段。
          Fee_terminal_Id
          21
          Unsigned Integer
          被計(jì)費(fèi)用戶的號(hào)碼(如本字節(jié)填空,則表示本字段無(wú)效,對(duì)誰(shuí)計(jì)費(fèi)參見(jiàn)Fee_UserType字段,本字段與Fee_UserType字段取0、1、2時(shí)互斥)
          TP_pId
          1
          Unsigned Integer
          GSM協(xié)議類型。詳細(xì)是解釋請(qǐng)參考GSM03.40中的9.2.3.9
          TP_udhi
          1
          Unsigned Integer
          GSM協(xié)議類型。詳細(xì)是解釋請(qǐng)參考GSM03.40中的9.2.3.23,僅使用1位,右對(duì)齊
          Msg_Fmt
          1
          Unsigned Integer
          信息格式
            0:ASCII串
            3:短信寫卡操作
            4:二進(jìn)制信息
            8:UCS2編碼
          15:含GB漢字  
          這個(gè)決定了Msg_Content字段的字節(jié)內(nèi)容應(yīng)該按照什么編碼來(lái)解碼/編碼。
          Msg_src
          6
          Octet String
          信息內(nèi)容來(lái)源(SP的企業(yè)代碼),例如919000。
          FeeType
          2
          Octet String
          資費(fèi)類別
          01:對(duì)“計(jì)費(fèi)用戶號(hào)碼”免費(fèi)
          02:對(duì)“計(jì)費(fèi)用戶號(hào)碼”按條計(jì)信息費(fèi)
          03:對(duì)“計(jì)費(fèi)用戶號(hào)碼”按包月收信息費(fèi)
          04:對(duì)“計(jì)費(fèi)用戶號(hào)碼”的信息費(fèi)封頂
          05:對(duì)“計(jì)費(fèi)用戶號(hào)碼”的收費(fèi)是由SP實(shí)現(xiàn)。
          通常值為02,注意這是一個(gè)字符串,并非整型。
          FeeCode
          6
          Octet String
          資費(fèi)代碼(以分為單位),如:“0050”代表人民幣0.50元。
          ValId_Time
          17
          Octet String
          存活有效期,格式遵循SMPP3.3協(xié)議
          At_Time
          17
          Octet String
          定時(shí)發(fā)送時(shí)間,格式遵循SMPP3.3協(xié)議。這個(gè)字段可以讓短信在規(guī)定的時(shí)間給手機(jī)用戶。一般情況下不填,保留為空字符串。
          Src_Id
          21
          Octet String
          源號(hào)碼
          SP的服務(wù)代碼或前綴為服務(wù)代碼的長(zhǎng)號(hào)碼, 網(wǎng)關(guān)將該號(hào)碼完整的填到SMPP協(xié)議Submit_SM消息相應(yīng)的source_addr字段,該號(hào)碼最終在用戶手機(jī)上顯示為短消息的主叫號(hào)碼。實(shí)際上就是服務(wù)代碼,可以是長(zhǎng)號(hào)碼
          DestUsr_tl
          1
          Unsigned Integer
          接收信息的用戶數(shù)量(小于100個(gè)用戶),通常是1。移動(dòng)是忌諱一條消息發(fā)給多個(gè)用戶的。
          Dest_terminal_Id
          21*DestUsr_tl
          Octet String
          接收短信的MSISDN號(hào)碼,一個(gè)類似字符串?dāng)?shù)組的結(jié)構(gòu)。受DestUsr_tl的約束,決定了本字段的長(zhǎng)度。
          Msg_Length
          1
          Unsigned Integer
          信息長(zhǎng)度(Msg_Fmt值為0時(shí):<160個(gè)字節(jié);其它<=140個(gè)字節(jié))。如果是ASCII碼,可以達(dá)到160個(gè)英文字母。原因是因?yàn)橛⑽淖帜竷H占用7bit,而中文等雙字節(jié)代碼需要16位,同時(shí)每一個(gè)字節(jié)最高為都占用,所以最多140個(gè)字節(jié),也就是70個(gè)漢字。
          Msg_Content
          Msg_length
          Octet String
          信息內(nèi)容
          Reserve
          8
          Octet String
          保留
          CMPP_SUBMIT消息長(zhǎng)度是可變的,將SP端的消息發(fā)送給ISMG,ISMG將返回一個(gè)MSGID給SP標(biāo)示此消息,之后(48小時(shí)以內(nèi),但一般最多幾分鐘內(nèi)就可),ISMG返回關(guān)于此消息的遞送報(bào)告。遞送報(bào)告同MO短消息是通過(guò)另外一個(gè)重要消息CMPP­_DELIVER來(lái)提交給SP的:
          CMPP­_DELIVER的各個(gè)字段:
          字段名
          字節(jié)數(shù)
          屬性
          描述
          Msg_Id
          8
          Unsigned Integer
          信息標(biāo)識(shí)
          生成算法如下:
          采用64位(8字節(jié))的整數(shù):
          (1)時(shí)間(格式為MMDDHHMMSS,即月日時(shí)分秒):bit64~bit39,其中
          bit64~bit61:月份的二進(jìn)制表示;
          bit60~bit56:日的二進(jìn)制表示;
          bit55~bit51:小時(shí)的二進(jìn)制表示;
          bit50~bit45:分的二進(jìn)制表示;
          bit44~bit39:秒的二進(jìn)制表示;
          (2)短信網(wǎng)關(guān)代碼:bit38~bit17,把短信網(wǎng)關(guān)的代碼轉(zhuǎn)換為整數(shù)填寫到該字段中。
          (3)序列號(hào):bit16~bit1,順序增加,步長(zhǎng)為1,循環(huán)使用。
          各部分如不能填滿,左補(bǔ)零,右對(duì)齊。
          Dest_Id
          21
          Octet String
          目的號(hào)碼
          SP的服務(wù)代碼,一般4--6位,或者是前綴為服務(wù)代碼的長(zhǎng)號(hào)碼;該號(hào)碼是手機(jī)用戶短消息的被叫號(hào)碼。
          Service_Id
          10
          Octet String
          業(yè)務(wù)類型,是數(shù)字、字母和符號(hào)的組合。
          TP_pid
          1
          Unsigned Integer
          GSM協(xié)議類型。詳細(xì)解釋請(qǐng)參考GSM03.40中的9.2.3.9
          TP_udhi
          1
          Unsigned Integer
          GSM協(xié)議類型。詳細(xì)解釋請(qǐng)參考GSM03.40中的9.2.3.23,僅使用1位,右對(duì)齊
          Msg_Fmt
          1
          Unsigned Integer
          信息格式
            0:ASCII串
            3:短信寫卡操作
            4:二進(jìn)制信息
            8:UCS2編碼
          15:含GB漢字   
          Src_terminal_Id
          21
          Octet String
          源終端MSISDN號(hào)碼(狀態(tài)報(bào)告時(shí)填為CMPP_SUBMIT消息的目的終端號(hào)碼)
          Registered_Delivery
          1
          Unsigned Integer
          是否為狀態(tài)報(bào)告
          0:非狀態(tài)報(bào)告(MO SMS)
          1:狀態(tài)報(bào)告
          此字段決定了CMPP­_DELIVER消息到底是手機(jī)上行一條消息到SP還是ISMG向SP報(bào)告之前發(fā)送的消息最終遞送狀態(tài)。
          Msg_Length
          1
          Unsigned Integer
          消息長(zhǎng)度。是指Msg_Content字段的長(zhǎng)度。
          Msg_Content
          Msg_length
          Octet String
          消息內(nèi)容。如果消息不是狀態(tài)報(bào)告,那么按照Msg_Fmt指示解碼為特定編碼的字符串內(nèi)容。
          Reserved
          8
          Octet String
          保留項(xiàng)
          如果是報(bào)告,那么Msg_Content將按照狀態(tài)報(bào)告結(jié)構(gòu)來(lái)解釋:
          字段名
          字節(jié)數(shù)
          屬性
          描述
          Msg_Id
          8
          Unsigned Integer
          信息標(biāo)識(shí)
          SP提交短信(CMPP_SUBMIT)操作時(shí),與SP相連的ISMG產(chǎn)生的Msg_Id。
          這個(gè)MSGID實(shí)際上就是SP之前發(fā)送一個(gè)CMPP_SUBMIT消息之后的CMPP_SUBMIT_RESP消息中返回的關(guān)于CMPP_SUBMIT消息的ISMG編號(hào).,根據(jù)此MSGID可以知道那條消息最終確定的遞送狀態(tài)。
          Stat
          7
          Octet String
          發(fā)送短信的應(yīng)答結(jié)果,含義與SMPP協(xié)議要求中stat字段定義相同,詳見(jiàn)下面。SP根據(jù)該字段確定被報(bào)告的CMPP_SUBMIT消息的處理狀態(tài)。
          Submit_time
          10
          Octet String
          YYMMDDHHMM(YY為年的后兩位00-99,MM:01-12,DD:01-31,HH:00-23,MM:00-59)
          Done_time
          10
          Octet String
          YYMMDDHHMM
          Dest_terminal_Id
          21
          Octet String
          目的終端MSISDN號(hào)碼(SP發(fā)送CMPP_SUBMIT消息的目標(biāo)終端)
          SMSC_sequence
          4
          Unsigned Integer
          取自SMSC發(fā)送狀態(tài)報(bào)告的消息體中的消息標(biāo)識(shí)。
          關(guān)于State字段,如下解釋:
          消息狀態(tài)名
          最終狀態(tài)
          描述
          DELIVERED
          DELIVRD
          消息到達(dá)目標(biāo)
          EXPIRED
          EXPIRED
          消息過(guò)期
          DELETED
          DELETED
          消息被刪除
          UNDELIVERABLE
          UNDELIV
          消息未被送達(dá)
          ACCEPTED
          ACCEPTD
          消息被認(rèn)可
          UNKNOWN
          UNKNOWN
          未知狀態(tài)
          REJECTED
          REJECTD
          消息被彈回
          其他消息結(jié)構(gòu),具體說(shuō)明見(jiàn)中移動(dòng)的CMPP協(xié)議。
           
          4.         安全驗(yàn)證
          CMPP協(xié)議在CMPP_CONNECT中傳遞驗(yàn)證消息。驗(yàn)證消息為9字節(jié)的0+移動(dòng)給出的密碼+當(dāng)前時(shí)間戳字節(jié)數(shù)組的MD5算法后的字節(jié)。時(shí)間戳為 月日時(shí)分秒,10位。代碼算法如下:
          private byte[] getMd5Code()
          {
                 byte[] buf=new byte[6+9+_Password.Length+10] ;   
                 byte[] s_a=Encoding.ASCII.GetBytes(_SystemID); //就是企業(yè)代碼
                 byte[] s_0={0,0,0,0,0,0,0,0,0};     //9字節(jié)的0,此處當(dāng)作右補(bǔ)0
                 byte[] s_p=Encoding.ASCII.GetBytes(_Password); //密碼
                 this._timestamp =getTimestamp();    //取得認(rèn)證碼時(shí)賦值字符串
                 byte[] s_t=Encoding.ASCII.GetBytes(_timestamp); //10位字符串字節(jié)數(shù)組
                 s_a.CopyTo(buf,0);   
                 s_0.CopyTo(buf,6);  
                 s_p.CopyTo(buf,6+9);  
                 s_t.CopyTo(buf,6+9+_Password.Length);
                 MD5 md5= new MD5CryptoServiceProvider(); //創(chuàng)建MD5類別
                 return(md5.ComputeHash(buf,0,buf.Length));
          }   
          其中g(shù)etTimestamp函數(shù)為返回例如“0710125959”(7月10號(hào)12點(diǎn)59分59秒)這樣的字符串,詳細(xì)代碼略過(guò),有興趣請(qǐng)查看本文的附件代碼。
           
          5.         廠商API問(wèn)題
          筆者公司所處廣東,廣東移動(dòng)提供了華為的以C 形式的API(SMEIDLL.dll),來(lái)幫助大家初期熟悉CMPP協(xié)議。但是,經(jīng)過(guò)開(kāi)發(fā)測(cè)試,發(fā)現(xiàn)華為的API至少存在幾個(gè)問(wèn)題:
          1、  封裝成幾個(gè)API函數(shù),但是由于CMPP自身的復(fù)雜性,導(dǎo)致這些函數(shù)丑陋無(wú)比,參數(shù)多,而且難以明晰含義。華為的API,內(nèi)部將CMPP的驗(yàn)證、事務(wù)階段分成幾個(gè)函數(shù)實(shí)現(xiàn),其中將發(fā)送SMS到ISMG功能以函數(shù)提供,竟然出現(xiàn)SubmitAExExEx之類的函數(shù)說(shuō)明。
          2、  CMPP的交互是異步的,需要多線程實(shí)現(xiàn)一邊發(fā)送,一邊接收反饋信息。此API應(yīng)當(dāng)是內(nèi)部維護(hù)一個(gè)線程進(jìn)行CMPP_SUBMIT消息發(fā)送,但是華為API卻通過(guò)空循環(huán)之類的操作等待ISMG返回CMPP_SUBMIT_RESP得到相應(yīng)的MSGID再返回(從而實(shí)現(xiàn)消息同步返回)。經(jīng)過(guò)測(cè)試,大約需要200毫秒,這個(gè)在實(shí)際SP的高性能需求場(chǎng)合根本無(wú)法滿足系統(tǒng)要求。
          3、  接收短信必須依靠程序主動(dòng)先發(fā)出函數(shù)HasDeliverMessage調(diào)用 ,得到有消息才可通過(guò)GetDeliverSMEx函數(shù)獲取消息,顯然,這種方式是低效率的,而且容易產(chǎn)生消息數(shù)據(jù)包丟失,表現(xiàn)為有些MO消息,SP接收不到。而且,令人疑惑的是,你還不能夠新開(kāi)一個(gè)線程專門來(lái)做判斷并接收MO的動(dòng)作,實(shí)際開(kāi)發(fā)中一旦采用線程來(lái)做就回發(fā)生內(nèi)存保護(hù)錯(cuò)誤(大概屬于同API自身的線程有沖突)。
          4、  返回錯(cuò)誤碼,往往又是華為自己定的一套錯(cuò)誤碼(大概華為設(shè)計(jì)此API為了適應(yīng)SMGP CMPP等多個(gè)協(xié)議),而且經(jīng)常變動(dòng),很是傷腦筋。
          基于以上理由,我認(rèn)為自己按照CMPP協(xié)議開(kāi)發(fā)一個(gè)SP端程序,比較能夠滿足一般SP的需求。
           
          四、C#實(shí)現(xiàn)
          1、CMPP協(xié)議實(shí)現(xiàn)類CMPPClient
          通過(guò)研究,筆者用C#寫了一組類實(shí)現(xiàn)自己的CMPP SP端程序(CMPPClient)。為了實(shí)現(xiàn)相關(guān)類,還需要編寫一些輔助類,并且首先要解決CMPP協(xié)議的數(shù)據(jù)結(jié)構(gòu)同C#的數(shù)據(jù)之間的轉(zhuǎn)換問(wèn)題。
          CMPP的Octet String 實(shí)際上相當(dāng)于C#中的byte[],所有CMPP消息的Octet String字段出了CMPP_SUBMIT和CMPP_DELIVER的msg_content字段外,其他的都可以認(rèn)為是ASCII編碼,所以全部可以采用System.Text.Encoding.ASCII進(jìn)行編碼和解碼;對(duì)于Msg_Content字段,由于一般情況下存在漢字信息傳輸.,所以默認(rèn)的編/解碼應(yīng)該為Encoding.Default,實(shí)際是什么編碼還要考察MSG_Fmt字段指示正文到底是什么編碼。
          對(duì)于Unsigned Integer 和Interger字段,需要按照網(wǎng)絡(luò)字節(jié)順序和x86機(jī)器的字節(jié)編碼順序?qū)φ贞P(guān)系進(jìn)行轉(zhuǎn)換,具體我設(shè)計(jì)了一個(gè)工具類提一些轉(zhuǎn)換方法使用:
          public class BIConvert  //字節(jié) 整形 轉(zhuǎn)換類 網(wǎng)絡(luò)格式轉(zhuǎn)換為內(nèi)存格式
                 {
                        public static byte[] Int2Bytes(uint i)  //轉(zhuǎn)換整形數(shù)據(jù)的網(wǎng)絡(luò)次序字節(jié)數(shù)組
                        {
                               byte[] t=BitConverter.GetBytes(i) ;
                               byte b=t[0];
                               t[0]=t[3];
                               t[3]=b;
                               b=t[1];
                               t[1]=t[2];
                               t[2]=b;
                               return(t);
                        }
           
                        public static uint Bytes2UInt(byte[] bs,int startIndex) //返回字節(jié)數(shù)組代表的整數(shù)數(shù)字,4個(gè)字節(jié)長(zhǎng)度的數(shù)組
                        {
                               byte[] t=new byte[4];
                               for(int i=0;i<4 && i< bs.Length-startIndex ;i++)
                               {
                                      t[i]=bs[startIndex+i];
                               } 
                               byte b=t[0];
                               t[0]=t[3];
                               t[3]=b;
                               b=t[1];
                               t[1]=t[2];
                               t[2]=b;
                               return(BitConverter.ToUInt32(t,0));
                        }
           
                        public static uint Bytes2UInt(byte[] bs)  //沒(méi)有指定起始索引
                        {
                               return( Bytes2UInt(bs,0));
                        }
                 }
           
          其次,為了實(shí)現(xiàn)收發(fā)數(shù)據(jù)的“全雙工”,需要設(shè)計(jì)至少兩個(gè)線程處理socket的讀取和數(shù)據(jù)包寫入。另外,為了自動(dòng)實(shí)現(xiàn)對(duì)數(shù)據(jù)鏈路的保持,以及自動(dòng)實(shí)現(xiàn)數(shù)據(jù)包重發(fā)機(jī)值,我還增加了一個(gè)值守線程,自動(dòng)處理以上問(wèn)題。詳細(xì)見(jiàn)后代碼。另外,消息中有很多同時(shí)間有關(guān)的字段,但是這些時(shí)間相關(guān)字段并非按照統(tǒng)一規(guī)格編碼的,這個(gè)需要仔細(xì)研究協(xié)議或者實(shí)現(xiàn)代碼。
          其三,為了解析/編碼數(shù)據(jù)包方便,我將SP端涉及到的消息以類的形式實(shí)現(xiàn),根據(jù)具體的消息類型,將數(shù)據(jù)包字節(jié)解析還原為特定的消息;另一方面,當(dāng)需要發(fā)送一些消息時(shí),將消息的各個(gè)字段,根據(jù)類型和編碼類型“組裝”成字節(jié)數(shù)組,以便Socket能夠發(fā)送出去。
          其四,為了達(dá)到及時(shí)處理短消息的收發(fā),我大量采用了C#事件觸發(fā)來(lái)達(dá)到消息通知目的,而且,也設(shè)計(jì)一組事件參數(shù),供事件的具體監(jiān)聽(tīng)者可以掌握需要的信息。
          其五,需要注意多線程間的同步問(wèn)題。
          其六,填寫CMPP_SUBMIT消息需要注意內(nèi)容編碼、計(jì)費(fèi)字段正確填寫
           
          2、事件模型
          大體上實(shí)現(xiàn)了十多個(gè)事件,這些事件具體為:
          當(dāng)CMPP_DELIVER消息送來(lái)的是短消息送達(dá)報(bào)告時(shí),發(fā)生消息送達(dá)報(bào)告事件:
          public delegate void ReportEventHandler(object sender, ReportEventArgs e); 
                 當(dāng)CMPP_DELIVER消息送來(lái)的是用戶手機(jī)MO短消息時(shí),發(fā)生短信到達(dá)事件,其他程序可以在處理此事件獲得消息的正文、手機(jī)號(hào)碼、SP服務(wù)號(hào)碼等信息:
          public delegate void SMSEventHandler(object sender, SMSEventArgs e);  
                 當(dāng)ISMG發(fā)出CMPP_TERMINATE消息時(shí),發(fā)生,具體的回應(yīng),我在具體實(shí)現(xiàn)中先自動(dòng)進(jìn)行了回復(fù),產(chǎn)生此事件僅僅向外部程序(此事件的截取者)表達(dá)收到此消息,需要進(jìn)行“善后清場(chǎng)”操作:
                 public delegate void TerminateEventHandler(object sender,TerminateEventArgs e);  
                        當(dāng)SP主動(dòng)終止連接時(shí),發(fā)出CMPP_TERMINATE消息,ISMG會(huì)響應(yīng)CMPP_TERMINATE_RESP消息,此事件表示收到此回應(yīng)
                 public delegate void TerminateRespEventHandler(object sender,TerminateRespEventArgs e); 
                 以下兩個(gè)事件針對(duì)鏈路保持消息CMPP_ACTIVE_TEST及CMPP_ACTIVE_TEST_RESP發(fā)生:
                 public delegate void TestEventHandler(object sender,TestEventArgs e);
                 public delegate void TestRespEventHandler(object sender,TestRespEventArgs e);
                 SP發(fā)出CMPP_CONNECT消息后,ISMG驗(yàn)證,然后發(fā)出CMPP_CONNECT_RESP消息,此時(shí)激活此事件:
                 public delegate void ConnectRespEventHandler(object sender,ConnectRespEventArgs e);
                 SP取消某條端消息,發(fā)出CMPP_CANCEL后,ISMG響應(yīng)此消息返回CMPP_CANCEL_RESP消息時(shí),激活事件:
                 public delegate void CancelRespEventHandler(object sender,CancelRespEventArgs e);
                 SP提交短信后,ISMG返回一個(gè)CMPP_SUBMIT_RESP 消息,包含“收條”(MSG_ID)在內(nèi),觸發(fā)此事件:
                 public delegate void SubmitRespEventHandler(object sender,SubmitRespEventArgs e);
                 查詢ISMG返回消息后,發(fā)生:
                 public delegate void QueryRespEventHandler(object sender,QueryRespEventArgs e);
                 當(dāng)SP驗(yàn)證通過(guò)后,作為應(yīng)用邏輯需要得到通知,我特此加了此事件:
                 public delegate void LogonSuccEventHandler(object sender,EventArgs e); //當(dāng)成功登錄系統(tǒng)
                 以下事件,不是基于CMPP消息,而是根據(jù)SP同ISMG消息隊(duì)列掃描后判斷觸發(fā)事件:
                 public delegate void SocketClosedEventHandler(object sender,EventArgs e); //當(dāng)套接字被檢測(cè)到關(guān)閉
                 public delegate void FailedItemDeletedEventHandler(object sender,WaitingQueueItemEventArgs e); //當(dāng)一條存在于等待隊(duì)列的消息超過(guò)60秒沒(méi)有回應(yīng)
          以上這些事件缺省實(shí)現(xiàn)保證了SP端CMPP客戶對(duì)于ISMG的響應(yīng)自動(dòng)化,提供觸發(fā)事件保證調(diào)用此客戶端類的系統(tǒng)可以通過(guò)事件發(fā)生準(zhǔn)確的控制SP端的內(nèi)部狀態(tài),獲取交互信息。
          另一方面,由于這些大多數(shù)事件發(fā)生于數(shù)據(jù)包達(dá)到后的處理,實(shí)際上需要處理事件程序一定要“迅速”解決,或者干脆將消息轉(zhuǎn)換為可以暫存的消息形式,由其他程序進(jìn)一步處理。CMPP的SP端要滿足大量短信息應(yīng)用需求,就必須嚴(yán)格控制消息交互處理邏輯不要太復(fù)雜,特別不要設(shè)計(jì)大量I/O處理;如果實(shí)在要處理,最好采用異步線程的方式來(lái)處理。
           
          3、為了提高效率,開(kāi)了3個(gè)線程:
                 RecvISMGMsgThread   用于處理接收ISMG發(fā)送過(guò)來(lái)的消息,并根據(jù)消息、消息解析后的字段內(nèi)容觸發(fā)相應(yīng)的事件。
                 SendSPMsgThread        用于處理向ISMG發(fā)送數(shù)據(jù)包。注意,有些消息(譬如CMPP_ACTIVE_TEST)是系統(tǒng)自己產(chǎn)生的。另外,有些消息是收到ISMG的消息后需要立即回應(yīng)給ISMG的,那么這些消息,全部進(jìn)入內(nèi)部維護(hù)的消息隊(duì)列(_outSeqQueue)。該隊(duì)列會(huì)自動(dòng)排序消息,所有需要發(fā)送的消息,進(jìn)入此隊(duì)列,本線程不斷從隊(duì)列取出需要發(fā)送的消息,轉(zhuǎn)換成數(shù)據(jù)包,通過(guò)Socket發(fā)送到ISMG.
                 DeamonThread      用于監(jiān)測(cè)數(shù)據(jù)連接socket是否可用,是否需要發(fā)出維持?jǐn)?shù)據(jù)連接的測(cè)試數(shù)據(jù)包;有些消息發(fā)送過(guò)去了,過(guò)了協(xié)議規(guī)定的時(shí)間仍然沒(méi)有收到RESP消息,那么需要將消息從已經(jīng)發(fā)送的隊(duì)列中提取,重新加入到發(fā)送隊(duì)列中,排隊(duì)后等待送出。
                 可以仔細(xì)分析提供的代碼,研究其中的具體實(shí)現(xiàn)。
           
          五、問(wèn)題小結(jié)
          根據(jù)自己的經(jīng)驗(yàn),覺(jué)得以下幾點(diǎn)對(duì)于整個(gè)系統(tǒng)開(kāi)發(fā)較為重要:
          1、一定要正確理解協(xié)議。
          很多網(wǎng)友交流時(shí)候,總抱怨協(xié)議濫,搞不定,其實(shí)很多原因?qū)儆谧约簺](méi)有清楚理解協(xié)議。從我的接觸的移動(dòng)ISMG來(lái)看,應(yīng)該說(shuō)實(shí)現(xiàn)協(xié)議還是很嚴(yán)格遵守CMPP的描述。倒是,一些網(wǎng)友自己開(kāi)發(fā)的模擬器不是很規(guī)范(不是批評(píng),鄭重聲明),需要自己在開(kāi)發(fā)時(shí)候引起注意。
          2、多線程互斥問(wèn)題。
          多個(gè)線程之間涉及一些隊(duì)列的操作,需要進(jìn)行同步鎖定,否則容易引起問(wèn)題。出現(xiàn)異常也需要及時(shí)捕獲,并紀(jì)錄作為錯(cuò)誤信息參考,便于排除bug。
          3、自己控制數(shù)據(jù)包流向和處理時(shí)間。
          由于設(shè)計(jì)目標(biāo)是高性能,所以在處理socket數(shù)據(jù)讀寫時(shí)候要注意對(duì)于一些事件處理不要過(guò)多消耗系統(tǒng)資源,避免引起數(shù)據(jù)包來(lái)不及處理而導(dǎo)致數(shù)據(jù)丟失。特別在數(shù)據(jù)繁忙時(shí)刻往往會(huì)使ISMG的吞吐性能下降,需要考慮對(duì)這種情況下的流量控制。有時(shí),你不能夠指望ISMG如你所愿及時(shí)回應(yīng)你,更為常見(jiàn)的是ISMG根本不返回RESP類型的數(shù)據(jù)包。另外,本協(xié)議處理數(shù)據(jù)收發(fā)采用阻塞Socket,有網(wǎng)友建議我采用異步非阻塞Socket,我想可能異步非阻塞Socket會(huì)更好。
          4、服務(wù)監(jiān)控問(wèn)題。
          由于一些意外,往往會(huì)導(dǎo)致數(shù)據(jù)連接被中斷,這是,需要建立超時(shí)重建連接的機(jī)制。我給出的例子并未很好解決,希望其他方家指正。
          5、字節(jié)順序問(wèn)題。
          這個(gè)問(wèn)題,對(duì)于初接觸socket編程的人士往往造成很大麻煩。不過(guò),CMPP協(xié)議設(shè)計(jì)的基本數(shù)據(jù)類型很簡(jiǎn)單,僅需要按照本例子參考即可解決。
          6、具體協(xié)議應(yīng)用問(wèn)題。
          本例僅僅是一個(gè)按照協(xié)議要求實(shí)現(xiàn)CMPP協(xié)議的類,完整的SP端方案需要結(jié)合自己公司的實(shí)際要求,改造或者重用本例。限于篇幅,文中僅僅能夠列出重點(diǎn)片斷,詳細(xì)細(xì)節(jié)清參考供下載的代碼(附注釋)。本文僅僅是針對(duì)CMPP2.0協(xié)議進(jìn)行討論開(kāi)發(fā),協(xié)議的詳情請(qǐng)從移動(dòng)夢(mèng)網(wǎng)(http://www.monternet.com/moneditor/cs/SP/cmcc/)下載。其他技術(shù)參考可以到如下處獲取,也可察看網(wǎng)友的貼字獲取進(jìn)一步詳細(xì)說(shuō)明:
                 天堂鳥(niǎo)交流論壇(http://www.spzone.net/bbs/index.asp
                 CSDN社區(qū) 移動(dòng)平臺(tái)
          (http://community.csdn.net/expert/forum.asp?url=/Expert/ForumsList.asp?roomid=63&typenum=1&whichpage=1)
                 SP論壇(http://www.spforum.net/jishu/Index.asp)
          如果你發(fā)現(xiàn)本人的實(shí)例存在問(wèn)題(我想那簡(jiǎn)直是一定的了),請(qǐng)不吝賜教myjobsdk@yahoo.com.cn。
           
           后記:現(xiàn)在CMPP3。0也就是移動(dòng)的MISC平臺(tái)版本的需要訂購(gòu)關(guān)系確定才可以計(jì)費(fèi)。不過(guò)不是本文討論的重點(diǎn)。

          posted @ 2012-07-19 01:46 火炎炎 閱讀(1181) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 桃园市| 慈溪市| 天全县| 古丈县| 永寿县| 辽源市| 乌鲁木齐市| 永吉县| 墨竹工卡县| 芜湖市| 青河县| 衢州市| 陆河县| 宜宾市| 新疆| 临朐县| 石门县| 黄平县| 长春市| 德清县| 广昌县| 禹城市| 无为县| 江西省| 靖宇县| 库车县| 洛南县| 雷山县| 婺源县| 乡宁县| 新闻| 宁蒗| 蓬溪县| 栖霞市| 阳曲县| 威信县| 玉屏| 隆化县| 汕尾市| 仁布县| 隆林|