中国移动短信⽹关CMPP3.0C#源代码:CMPP30类(1)
(转)
这是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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。