Tiray.SMSTiray.SMSTiray.SMSTiray.SMSTiray.SMSTiray.SMS

這是2005年6月云南移動短信網關升級到3.0時寫的,在SP那穩定運行了很長時間的。因為SP倒閉了,貼出來給有興趣的朋友參考。
優點:支持多線程、滑動窗口、異步發送、全事件模式、自動識別ASCII、GBK、UCS-2
缺點:不支持長短信自動分頁、不支持PROVISION接口(偶的PROVISION接口是用WEB SERVICE實現的)

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using System.Net.Sockets;
using System.Security.Cryptography;

namespace Tiray.SMS
{
?/// <summary>
?/// CMPP30 的摘要說明。
?/// </summary>
?

?public class CMPP30
?{
??#region Constants
??public const Byte CMPP_VERSION_30???=0x30;
??public const Byte CMPP_VERSION_21???=0x20;
??public const UInt32 CMD_ERROR????=0xFFFFFFFF;
??public const UInt32 CMD_CONNECT????=0x00000001;???
??public const UInt32 CMD_CONNECT_RESP??=0x80000001;
??public const UInt32 CMD_TERMINATE???=0x00000002;?//?終止連接
??public const UInt32 CMD_TERMINATE_RESP??=0x80000002;?//?終止連接應答
??public const UInt32 CMD_SUBMIT????=0x00000004;?//?提交短信
??public const UInt32 CMD_SUBMIT_RESP???=0x80000004;?//?提交短信應答
??public const UInt32 CMD_DELIVER????=0x00000005;?//?短信下發
??public const UInt32 CMD_DELIVER_RESP??=0x80000005;?//?下發短信應答
??public const UInt32 CMD_QUERY????=0x00000006;?//?短信狀態查詢
??public const UInt32 CMD_QUERY_RESP???=0x80000006;?//?短信狀態查詢應答
??public const UInt32 CMD_CANCEL????=0x00000007;?//?刪除短信
??public const UInt32 CMD_CANCEL_RESP???=0x80000007;?//?刪除短信應答
??public const UInt32 CMD_ACTIVE_TEST???=0x00000008;?//?激活測試
??public const UInt32 CMD_ACTIVE_TEST_RESP?=0x80000008;?//?激活測試應答
??#endregion

??#region Protected Member Variables;
??protected string m_strSPID;//SP企業代碼;
??protected string m_strPassword;//SP密碼;
??protected string m_strAddress;//短信網關地址
??protected int m_iPort;//短信網關端口號;
??protected static UInt32 m_iSeqID=0;//命令的序號

??protected int m_iSlidingWindowSize=16;//滑動窗口大小(W)
??protected int m_iActiveTestSpan=150;//ACTIVETEST的時間間隔(C,以秒為單位),標準為180
??protected DateTime m_dtLastTransferTime;//最近一次網絡傳輸時間
??protected int m_iTimeOut=60;//響應超時時間(T,以秒為單位)
??protected int m_iSendCount=3;//最大發送次數(N)
??protected DATA_PACKAGE[] SlidingWindow=null;
??protected TcpClient m_TcpClient=null;
??protected NetworkStream m_NetworkStream=null;
??protected Queue m_MessageQueue=null;//消息隊列,用于保存所有待發送數據
??protected int m_iTcpClientTimeout=5;//TcpClient接收和發送超時(以秒為單位)
??protected int m_iSendSpan=10;//發送間隔,以毫秒為單位
??#endregion

??#region Worker Thread
??protected System.Threading.Thread m_SendThread=null;
??protected System.Threading.Thread m_ReceiveThread=null;
??
??protected AutoResetEvent m_eventSendExit=new AutoResetEvent(false);
??protected AutoResetEvent m_eventReceiveExit=new AutoResetEvent(false);
??protected AutoResetEvent m_eventConnect=new AutoResetEvent(false);
??protected AutoResetEvent m_eventDisconnect=new AutoResetEvent(false);
??protected ManualResetEvent m_eventSend=new ManualResetEvent(false);
??protected ManualResetEvent m_eventReceive=new ManualResetEvent(false);

??protected void SendThreadProc()
??{
???while(true)
???{
????if(m_eventSendExit.WaitOne(TimeSpan.FromMilliseconds(0),false))?
????{
?????Disconnect();
?????break;
????}
????if(m_eventConnect.WaitOne(TimeSpan.FromMilliseconds(0),false))//連接
????{
?????if(Connect())//連接上,開始發送和接收
?????{
??????m_eventSend.Set();
??????m_eventReceive.Set();
?????}
?????else
?????{
??????Close();
??????Thread.Sleep(5000);
??????m_eventConnect.Set();
?????}
????}
????if(m_eventDisconnect.WaitOne(TimeSpan.FromMilliseconds(0),false))//拆除連接
????{
?????m_eventSend.Reset();
?????m_eventReceive.Reset();
?????Disconnect();
?????Thread.Sleep(5000);
?????m_eventConnect.Set();
????}
????if((m_eventSend.WaitOne(TimeSpan.FromMilliseconds(0),false))&&(m_NetworkStream!=null))
????{
?????bool bOK=true;
?????ActiveTest();????
?????Monitor.Enter(SlidingWindow);
?????for(int i=0;i<m_iSlidingWindowSize;i++)//首先用消息隊列中的數據填充滑動窗口
?????{
??????if(SlidingWindow[i].Status==0)
??????{
???????DATA_PACKAGE dp=new DATA_PACKAGE();
???????dp.Data=null;
???????Monitor.Enter(m_MessageQueue);
???????if(m_MessageQueue.Count>0)
???????{
????????dp =(DATA_PACKAGE)m_MessageQueue.Dequeue();
????????SlidingWindow[i]=dp;
???????}
???????Monitor.Exit(m_MessageQueue);

??????}

?????}
?????for(int i=0;i<m_iSlidingWindowSize;i++)
?????{
??????DATA_PACKAGE dp =SlidingWindow[i];
??????if((dp.Status==1)&&(dp.SendCount==0))//第一次發送
??????{
???????bOK=Send(dp);
???????if((bOK)&&(dp.Command>0x80000000))//發送的是Response類的消息,不需等待Response
???????{
????????SlidingWindow[i].Status=0;//清空窗口
???????}
???????else if((bOK)&&(dp.Command<0x80000000))//發送的是需要等待Response的消息
???????{
????????
????????SlidingWindow[i].SendTime=DateTime.Now;
????????SlidingWindow[i].SendCount++;
???????}
???????else
???????{
????????bOK=false;
????????break;//網絡出錯
???????}
???????
??????}
??????else if((dp.Status==1)&&(dp.SendCount>0))//第N次發送
??????{
???????if(dp.SendCount>m_iSendCount-1)//已發送m_iSendCount次,丟棄數據包
???????{
????????SlidingWindow[i].Status=0;//清空窗口
????????if(dp.Command==CMPP30.CMD_ACTIVE_TEST)//是ActiveTest
????????{
?????????bOK=false;
?????????break;//ActiveTest出錯
????????}

????????
???????}
???????else
???????{
????????TimeSpan ts=DateTime.Now-dp.SendTime;
????????if(ts.TotalSeconds>=m_iTimeOut)//超時后未收到回應包
????????{
?????????bOK=Send(dp);//再次發送
?????????if(bOK)
?????????{
??????????SlidingWindow[i].SendTime=DateTime.Now;
??????????SlidingWindow[i].SendCount++;
?????????}
?????????else
?????????{
??????????bOK=false;
??????????break;//網絡出錯
?????????}
????????}
???????}

??????}
?????}
?????Monitor.Exit(SlidingWindow);
?????

?????if(!bOK)
?????{
??????Close();//關閉連接
??????Thread.Sleep(5000);//等待5秒
??????m_eventSend.Reset();
??????m_eventConnect.Set();
?????}
????}
???}

??}
??protected void ReceiveThreadProc()
??{
???while(true)
???{
????if(m_eventReceiveExit.WaitOne(TimeSpan.FromMilliseconds(0),false))?
????{
?????break;
????}
????if((m_eventReceive.WaitOne(TimeSpan.FromMilliseconds(0),false)&&(m_NetworkStream!=null)))
????{
?????CMPP_HEAD Head=ReadHead();
?????if(Head.CommandID==CMPP30.CMD_SUBMIT_RESP)
?????{
??????ReadSubmitResp(Head);
?????}
?????else if(Head.CommandID==CMPP30.CMD_ACTIVE_TEST)
?????{
??????ActiveTestResponse(Head.SequenceID);
?????}
?????else if(Head.CommandID==CMPP30.CMD_ACTIVE_TEST_RESP)
?????{
??????ReadActiveTestResponse(Head);
?????}
?????else if(Head.CommandID==CMPP30.CMD_DELIVER)
?????{
??????ReadDeliver(Head);
?????}
?????else if(Head.CommandID==CMPP30.CMD_ERROR)//網絡故障
?????{
??????m_eventReceive.Reset();
??????m_eventDisconnect.Set();
?????}
????}

???}
??}
??#endregion

??#region Constructor

??public CMPP30(string SPID,string Password,string Address,int Port)
??{
???m_strSPID=SPID;
???m_strPassword=Password;
???m_strAddress=Address;
???m_iPort=Port;
???SlidingWindow=new DATA_PACKAGE[m_iSlidingWindowSize];//初始化滑動窗口
???for(int i=0;i<m_iSlidingWindowSize;i++)
????SlidingWindow[i]=new DATA_PACKAGE();
???m_MessageQueue=new Queue();

??}
??#endregion

??#region SMSEvents
??public event Tiray.SMS.SMSEventHandler SMSStateChanged;

??protected? void RaiseEvent(SMS_STATE State,Object Data)
??{
???if(null!=SMSStateChanged)
???{
????SMSEventArgs e=new SMSEventArgs();
????e.Time=DateTime.Now;
????e.State=State;
????e.Data=Data;
????SMSStateChanged(this,e);
???}

??}
??#endregion

??#region Protected Methods
??protected UInt32 TimeStamp(DateTime dt)
??{
???string str=String.Format("{0:MMddhhmmss}",dt);
???return Convert.ToUInt32(str);
??}
??protected UInt32 CreateID()
??{
???UInt32 id=m_iSeqID;
???m_iSeqID++;
???if(m_iSeqID>UInt32.MaxValue)
????m_iSeqID=0;
???return id;
??}
??protected Byte[] CreateDigest(DateTime dt)
??{
???int iLength=25+m_strPassword.Length;
???Byte[] btContent=new Byte[iLength];
???Array.Clear(btContent,0,iLength);
???int iPos=0;
???foreach(char ch in m_strSPID)
???{
????btContent[iPos]=(Byte)ch;
????iPos++;
???}
???iPos+=9;
???foreach(char ch in m_strPassword)
???{
????btContent[iPos]=(Byte)ch;
????iPos++;
???}
???string strTimeStamp=String.Format("{0:MMddhhmmss}",dt);
???foreach(char ch in strTimeStamp)
???{
????btContent[iPos]=(Byte)ch;
????iPos++;
???}
???MD5 md5 = new MD5CryptoServiceProvider();
???return md5.ComputeHash(btContent);
??}

??protected bool Close()
??{
???if(m_NetworkStream!=null)
????m_NetworkStream.Close();
???if(m_TcpClient!=null)
????m_TcpClient.Close();
???
???m_TcpClient=null;
???m_NetworkStream=null;

???return true;

??}

??protected bool Connect()
??{
???bool bOK=true;
???string strError=string.Empty;
???CMPP_CONNECT_RESP resp=new CMPP_CONNECT_RESP();
???try
???{
????m_TcpClient=new TcpClient();
????m_TcpClient.ReceiveTimeout=m_TcpClient.SendTimeout=m_iTcpClientTimeout*1000;
????m_TcpClient.Connect(m_strAddress,m_iPort);
????m_NetworkStream=m_TcpClient.GetStream();
????
????DateTime dt=DateTime.Now;
????CMPP_CONNECT conn=new CMPP_CONNECT();
????conn.Head=new CMPP_HEAD();
????conn.Head.CommandID=CMPP30.CMD_CONNECT;
????conn.Head.SequenceID=CreateID();
????conn.SourceAddress=m_strSPID;
????conn.TimeStamp=TimeStamp(dt);
????conn.AuthenticatorSource=CreateDigest(dt);
????conn.Version=CMPP_VERSION_30;
????Byte[] buffer=conn.GetBuffer();
????m_NetworkStream.Write(buffer,0,(Int32)conn.Head.TotalLength);
????int iSpan=0;
????bool bTimeOut=false;
????while(!m_NetworkStream.DataAvailable)//等待RESPONSE 5秒
????{
?????Thread.Sleep(10);
?????iSpan++;
?????if(iSpan>500)
?????{
??????bTimeOut=true;
??????break;
?????}

????}
????if(!bTimeOut)
????{
?????CMPP_HEAD Head=ReadHead();
?????if(Head.CommandID==CMD_CONNECT_RESP)
?????{
??????resp=ReadConnectResp(Head);
??????if(resp.Status==0)
???????bOK=true;
??????else
??????{
???????bOK=false;
???????strError="未正確接收CONNECT_RESP";
??????}
?????}
????}
????else
????{
?????bOK=false;
?????strError="等待CONNECT_RESP超時";
????}
???}
???catch(Exception e)
???{
????strError=e.Message;
????bOK=false;
???}

???if(bOK)
????RaiseEvent(SMS_STATE.SP_CONNECT,resp);
???else
????RaiseEvent(SMS_STATE.SP_CONNECT_ERROR,strError);

???return bOK;

??}
??protected bool Disconnect()
??{
???bool bOK=true;
???string strError=string.Empty;
???try
???{
????DateTime dt=DateTime.Now;
????CMPP_HEAD Head=new CMPP_HEAD();
????Head.CommandID=CMPP30.CMD_TERMINATE;
????Head.SequenceID=CreateID();
????Head.TotalLength=(UInt32)Marshal.SizeOf(Head);
????Byte[] buffer=Head.GetBuffer();
????m_NetworkStream.Write(buffer,0,(Int32)Head.TotalLength);
????int iSpan=0;
????bool bTimeOut=false;
????while(!m_NetworkStream.DataAvailable)//等待RESPONSE 5秒
????{
?????Thread.Sleep(10);
?????iSpan++;
?????if(iSpan>500)
?????{
??????bTimeOut=true;
??????break;
?????}

????}
????if(!bTimeOut)
????{
?????Head=ReadHead();
?????if(Head.CommandID==CMD_TERMINATE_RESP)
??????bOK=true;
?????else
?????{
??????bOK=false;
??????strError="未正確接收TERMINATE_RESP";
?????}
????}
????else
????{
?????bOK=false;
?????strError="等待TERMINATE_RESP超時";
????}

???}
???catch (Exception ex)
???{
????bOK=false;
????strError=ex.Message;
???}
???if(m_NetworkStream!=null)
????m_NetworkStream.Close();
???if(m_TcpClient!=null)
????m_TcpClient.Close();
???m_TcpClient=null;
???m_NetworkStream=null;

???if(bOK)
????RaiseEvent(SMS_STATE.SP_DISCONNECT,null);
???else
????RaiseEvent(SMS_STATE.SP_DISCONNECT_ERROR,strError);

???return bOK;
??}
??protected bool Send(DATA_PACKAGE dp)
??{
???bool bOK=true;
???string strError=string.Empty;
???SMS_STATE state=SMS_STATE.UNKNOW_ERROR;
???try
???{
????Thread.Sleep(m_iSendSpan);
????Byte[] btData=null;
????if(dp.Command==CMD_ACTIVE_TEST)
????{
?????btData=((CMPP_HEAD)dp.Data).GetBuffer();
?????state=SMS_STATE.ACTIVE_TEST;
????}
????else if(dp.Command==CMD_ACTIVE_TEST_RESP)
????{
?????btData=((CMPP_ACTIVE_TEST_RESP)dp.Data).GetBuffer();
?????state=SMS_STATE.ACTIVE_TEST_RESPONSE;
????}
????else if(dp.Command==CMD_DELIVER_RESP)
????{
?????btData=((CMPP_DELIVER_RESP)dp.Data).GetBuffer();
?????state=SMS_STATE.DELIVER_RESPONSE;
????}
????else if(dp.Command==CMD_SUBMIT)
????{
?????btData=((CMPP_SUBMIT)dp.Data).GetBuffer();
?????state=SMS_STATE.SUBMIT;
????}
????m_NetworkStream.Write(btData,0,btData.Length);
????m_dtLastTransferTime=DateTime.Now;
???}
???catch(Exception ex)
???{
????
????bOK=false;
????strError=ex.Message;
???}
???if(bOK)
???{
????RaiseEvent(state,dp.Data);
???}
???else
???{
????if(state==SMS_STATE.ACTIVE_TEST)
?????state=SMS_STATE.ACTIVE_TEST_ERROR;
????else if(state==SMS_STATE.ACTIVE_TEST_RESPONSE)
?????state=SMS_STATE.ACTIVE_TEST_RESPONSE_ERROR;
????else if(state==SMS_STATE.DELIVER_RESPONSE)
?????state=SMS_STATE.DELIVER_RESPONSE_ERROR;
????else if(state==SMS_STATE.SUBMIT)
?????state=SMS_STATE.SUBMIT_ERROR;

????RaiseEvent(state,strError);
???}
???return bOK;

??}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/389173.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/389173.shtml
英文地址,請注明出處:http://en.pswp.cn/news/389173.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

水文分析提取河網_基于圖的河網段地理信息分析排序算法

水文分析提取河網The topic of this article is the application of information technologies in environmental science, namely, in hydrology. Below is a description of the algorithm for ranking rivers and the plugin we implemented for the open-source geographic…

請不要更多的基本情節

“If I see one more basic blue bar plot…”“如果我再看到一個基本的藍色條形圖……” After completing the first module in my studies at Flatiron School NYC, I started playing with plot customizations and design using Seaborn and Matplotlib. Much like doodl…

Powershell-獲取DHCP地址租用信息

需求&#xff1a;業務需要獲取現階段DHCP服務器所有地址租用信息。 1.首先查看DHCP相關幫助信息&#xff1a;2.確定執行命令并獲取相關幫助信息&#xff1a;help Get-DhcpServerv4Scope 名稱 Get-DhcpServerv4Scope 語法 Get-DhcpServerv4Scope [[-ScopeId] <ipaddress[]>…

c# 對COM+對象反射調用時地址參數處理 c# 對COM+對象反射調用時地址參數處理

使用反射的方式調用組件里面的方法&#xff0c;經常會遇見一些象地址參數的處理&#xff0c;在C#中表現為ref參數&#xff0c;比如用C#寫了一個裝配件&#xff0c;里面有一個方法openProcedure(string ProcName,int paraCount,ref string[] parameters)&#xff0c;最后有一個r…

android觸摸消息的派發過程

1.觸摸消息是消息獲取模塊直接派發給應用程序的。 2.觸摸消息在處理時&#xff0c; 需要根據觸摸坐標計算該消息應該派發給哪個View/ViewGroup, 在案件取消處理中不存在 該計算過程。 3.沒有類似”系統按鍵”的”系統觸摸鍵”&#xff0c; 應用程序可完全控制觸摸行為。 4.子…

python 交互式流程圖_使用Python創建漂亮的交互式和弦圖

python 交互式流程圖Python中的數據可視化 (Data Visualization in Python) R vs Python is a constant tussle when it comes to what is the best language, according to data scientists. Though each language has it’s strengths, R, in my opinion has one cutting-edg…

機器學習解決什么問題_機器學習幫助解決水危機

機器學習解決什么問題According to Water.org and Lifewater International, out of 57 million people in Tanzania, 25 million do not have access to safe water. Women and children must travel each day multiple times to gather water when the safety of that water …

遞歸原來可以so easy|-連載(3)

本期我們再通過幾個例子&#xff0c;加深遞歸的理解和熟練度。 上期有一個練習題&#xff1a;用遞歸逆序輸出一個包含整型數據的鏈表。 先完成這個練習題。 對于程序員來說&#xff0c;代碼是最好的溝通工具&#xff0c;什么都不說&#xff0c;上代碼&#xff1a; public class…

Viewport3D 類Viewport3D 類Viewport3D 類

.NET Framework 類庫Viewport3D 類更新&#xff1a;2007 年 11 月為三維可視內容提供呈現圖面。命名空間&#xff1a; System.Windows.Controls程序集&#xff1a; PresentationFramework&#xff08;在 PresentationFramework.dll 中&#xff09;用于 XAML 的 XMLNS&#xf…

升級android 6.0系統

How to Fix errors by manually flashing Marshmallow update 鏡像下載for nexus Factory image Step 1: Download the [Marshmallow factory image](http://www.theandroidsoul.com/download-mra58k-android-6-0-marshmallow-update-released-for-nexus-5-nexus-6-nexus-9-n…

AGC 022 B - GCD Sequence

題面在這里&#xff01; 鍛煉腦子的小構造題。。。 一開始被 a[]<30000 且 序列 gcd 1所困擾&#xff0c;但是發現這并沒有什么&#xff0c;因為我接下來發現了一種總是能構造出 序列和是6的倍數的方案。 首先如果 n3 的話輸出樣例&#xff0c;因為只有這種情況沒法用我的方…

最接近原點的 k 個點_第K個最接近原點的位置

最接近原點的 k 個點In this article, I will be explaining to you one of the problems that you may find when tackling questions in data structures and algorithm. You will need some basic knowledge of data structures in order to understand the optimized solut…

網絡瀏覽器如何工作

Behind the scenes of modern Web Browsers現代Web瀏覽器的幕后花絮 The Web Browser is inarguably the most common portal for users to access the web. The advancement of the web browsers (through the series of history) has led many traditional “thick clients”…

讓自己的頭腦極度開放

為什么80%的碼農都做不了架構師&#xff1f;>>> 一. 頭腦封閉和頭腦開放 頭腦封閉 你是否經常有這樣的經歷&#xff0c;在一次會議或者在一次小組討論時&#xff0c;當你提出一個觀點而被別人否定時&#xff0c;你非常急迫地去反駁別人&#xff0c;從而捍衛自己的尊…

簡介DOTNET 編譯原理 簡介DOTNET 編譯原理 簡介DOTNET 編譯原理

簡介DOTNET 編譯原理 相信大家都使用過 Dotnet &#xff0c;可能還有不少高手。不過我還要講講Dotnet的基礎知識&#xff0c;Dotnet的編譯原理。 Dotnet是一種建立在虛擬機上執行的語言&#xff0c;它直接生成 MSIL 的中間語言&#xff0c;再由DotNet編譯器 JIT 解釋映象為本機…

RecyclerView詳細了解

關于RecyclerView大家都不陌生了&#xff0c;它的使用也越來越受歡迎&#xff0c;現在總體了解一下RecyclerView的作用&#xff0c;為什么會有RecyclerView呢&#xff0c;我用ListView也能干所有的事情啊&#xff0c;尺有所短&#xff0c;寸有所長&#xff0c;先來看看Recycler…

案例與案例之間的非常規排版

In 1929 the Cond Nast publishing group brought Russian-born Mehemed Fehmy Agha—who had been working for the German edition of Vogue magazine—to America as art director for House & Garden, Vanity Fair, and the senior edition of Vogue.1929年&#xff0c…

熊貓分發_熊貓新手:第二部分

熊貓分發This article is a continuation of a previous article which kick-started the journey to learning Python for data analysis. You can check out the previous article here: Pandas for Newbies: An Introduction Part I.本文是上一篇文章的延續&#xff0c;該文…

淺析微信支付:申請退款、退款回調接口、查詢退款

本文是【淺析微信支付】系列文章的第八篇&#xff0c;主要講解商戶如何處理微信申請退款、退款回調、查詢退款接口&#xff0c;其中有一些坑的地方&#xff0c;會著重強調。 淺析微信支付系列已經更新七篇了喲&#xff5e;&#xff0c;沒有看過的朋友們可以看一下哦。 淺析微信…

view工作原理-計算視圖大小的過程(onMeasure)

view的視圖有兩種情況&#xff1a; 內容型視圖&#xff1a;由視圖的內容決定其大小。圖形型視圖&#xff1a;父視圖為view動態調整大小。 ### measure的本質 把視圖布局使用的“相對值”轉化成具體值的過程&#xff0c;即把WRAP_CONTENT,MATCH_PARENT轉化為具體的值。 measur…