您的位置:首页 > 其它

中国移动CMPP接口

2011-03-21 17:25 134 查看
下载参考程序 :http://download.csdn.net/detail/adama119/4189313

短信行业已经很成熟了,到处可以找到资料。本人在这个行业干过几年,做过3套短信平台都在省级单位省用,做的最复杂的自然是SP的应用,曾经在广电集团工作时做的内容确实非常复杂自己都觉得头疼,当然也和水平有限有关。

2010年底给江苏某国企做了一套行业应用的短信系统,做短信平台大量工作还是围绕业务开发WEB方面内容。这次网关客户端的是用C#开发的,目标为50条/秒,性能上应该没什么问题,支持普通短信和wappush但是长短信对方没要就没写,需要的朋友可以自行修改开发。以下贴出CMPP2.0源代码给各位需要的朋友做个参考,运行到现在没有发现任何问题。这里只贴出cmpp接口,至于程序就自己做吧,如果需要也可以联系我。

邮箱 spf193@gmail.com

//------------------------------------------------------------------------------

//文件Client.cs

//------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

using System.Net.Sockets;

using System.Collections;

namespace AsiaINFO.SMS.CMPP2

{

/// <summary>

/// @Description:CMPP2 短消息移动网关客户端

/// @Author:Adama SUN

/// @Mail:spf193@gmail.com

/// @Copyright (C) 2010 AsiaINFO. All rights reserved.

/// </summary>

public class CMPPClient

{

public delegate void MsgEventDelegate(string msg);

/// <summary>

/// 线程状态通知

/// </summary>

/// <param name="sender">线程</param>

/// <param name="state">线程状态</param>

public delegate void ThreadStateDelegate(object sender, ThreadState state);

/// <summary>

/// 构造

/// </summary>

/// <param name="queue">CMPP接口 接收数据队列</param>

/// <param name="cmppSyncEvents">CMPP接口信号:检查是否需要退出线程,CMPP接口新数据到达(通知)</param>

public CMPPClient(Queue<byte[]> queue, SyncEvents cmppSyncEvents)

{

if (queue == null || cmppSyncEvents == null)

throw new Exception("参数不能为空!");

_receiveQueue = queue;

_syncEvents = cmppSyncEvents;

}

#region private field

private Queue<byte[]> _receiveQueue;//接收队列

private SyncEvents _syncEvents;//信号

// private string _Host; //主机

// private int _Port; //端口

private string _Source_Addr;

// private string _Password; //密码

private bool _IsConnected=false; //连接状态

private static object _SyncLockObject = new object(); //锁

private TcpClient tc;

private NetworkStream _NetworkStream;

private Thread _ReadResponseThread;

private object _syncIsConnectedObject = new object();

#endregion

#region public property

/// <summary>

/// 连接状态

/// </summary>

public bool IsConnected

{

get

{

lock (_syncIsConnectedObject)

{

return this._IsConnected;

}

}

set

{

lock (_syncIsConnectedObject)

{

this._IsConnected = value;

}

}

}

#endregion

#region public event

/// <summary>

/// 信息事件

/// </summary>

public event MsgEventDelegate MsgEvent;

/// <summary>

/// 错误事件

/// </summary>

public event MsgEventDelegate ErrorEvent;

/// <summary>

/// 退出事件

/// </summary>

public event ThreadStateDelegate ThreadStateEvent;

#endregion

#region public methos

/// <summary>

/// 连接

/// </summary>

/// <param name="Host">主机地址</param>

/// <param name="Port">端口</param>

/// <param name="UserID">用户名</param>

/// <param name="Password">密码</param>

/// <param name="SequenceId">序列好</param>

/// <returns></returns>

public void Connect(string Host, int Port, string UserID, string Password, uint SequenceId)

{

// this._Host = Host;

// this._Port = Port;

this._Source_Addr = UserID;

// this._Password = Password;

// DateTime ts = DateTime.Now;

//CMPP_CONNECT connect = new CMPP_CONNECT(this._Source_Addr, this._Password, ts, 1, SequenceId);

CMPP_CONNECT connect = new CMPP_CONNECT(this._Source_Addr, Password, DateTime.Now, 0x20, SequenceId);

tc = new TcpClient();

tc.Connect(Host, Port);

if (this._NetworkStream != null)

{

try

{

this._NetworkStream.Close();

this._NetworkStream = null;

}

catch (Exception) { }

}

this._NetworkStream = tc.GetStream();

this.WriteToStreamWithLock(connect.ToBytes(), this._NetworkStream);

this.StartRun();

}

/// <summary>

/// 中断

/// </summary>

/// <param name="SequenceId"></param>

public void Terminate(uint SequenceId)

{

MessageHeader terminate = new MessageHeader(MessageHeader.Length, CMPP_Command_Id.CMPP_TERMINATE, SequenceId);

// OnMsg(terminate.ToString());

this.WriteToStreamWithLock(terminate.ToBytes(), this._NetworkStream);

}

/// <summary>

/// CMPP_ACTIVE_TEST

/// </summary>

/// <param name="SequenceId"></param>

public void ActiveTest(uint SequenceId)

{

MessageHeader activeTest = new MessageHeader(MessageHeader.Length, CMPP_Command_Id.CMPP_ACTIVE_TEST, SequenceId);

//byte[] activeTest = activeTest.ToBytes();

//OnShowMsg(activeTest.ToString());

// Console.WriteLine("Request:/r/n{0}", activeTest.ToString());

this.WriteToStreamWithLock(activeTest.ToBytes(), this._NetworkStream);

// this.StartRun();

}

/// <summary>

/// CMPP_ACTIVE_TEST_RESP

/// </summary>

/// <param name="SequenceId"></param>

public void ActiveResp(uint SequenceId)

{

CMPP_ACTIVE_TEST_RESP response = new CMPP_ACTIVE_TEST_RESP(SequenceId);

this.WriteToStreamWithLock(response.ToBytes(), this._NetworkStream);

}

/// <summary>

/// 发送CMPP_DELIVER_RESP

/// </summary>

/// <param name="Msg_Id"></param>

/// <param name="Result"></param>

public void DeliverResp(ulong Msg_Id, uint Result,uint SequenceId)

{

CMPP_DELIVER_RESP deliverResp = new CMPP_DELIVER_RESP(Msg_Id, Result, SequenceId);

this.WriteToStreamWithLock(deliverResp.ToBytes(), this._NetworkStream);

}

/// <summary>

/// 查询发送短信状态

/// </summary>

/// <param name="Time"></param>

/// <param name="QueryType"></param>

/// <param name="QueryCode"></param>

/// <param name="Reserve"></param>

/// <param name="SequenceId"></param>

public void Query(DateTime Time, uint QueryType, string QueryCode, string Reserve, uint SequenceId)

{

CMPP_QUERY query = new CMPP_QUERY(Time, QueryType, QueryCode, Reserve, SequenceId);

this.WriteToStreamWithLock(query.ToBytes(), this._NetworkStream);

}

/// <summary>

/// 发送短信

/// </summary>

/// <param name="MsgId">信息标识</param>

/// <param name="mobile">接收短信的号码与计费号码</param>

/// <param name="MsgContent">短信内容</param>

/// <param name="SequenceId">序列号</param>

/// <param name="Service_Id">业务代码</param>

/// <param name="FeeType">资费类别</param>

/// <param name="FeeCode">资费代码(以分为单位)</param>

/// <param name="Src_Id">源号码</param>

/// <param name="LinkId"></param>

public void Submit(ulong MsgId, string mobile, string MsgContent, uint SequenceId, string Service_Id, string FeeType, string FeeCode, string Src_Id, string WapURL)

{

if (mobile != null && mobile.Length == 11)

mobile = "86" + mobile;

Submit(MsgId, mobile, new string[] { mobile }, MsgContent, SequenceId, Service_Id, FeeType, FeeCode, Src_Id, WapURL);

}

/// <summary>

/// 发送短信

/// </summary>

/// <param name="MsgId">信息标识</param>

/// <param name="FeeTerminalId">被计费用户的号码</param>

/// <param name="DestTerminalId">接收短信的MSISDN号码_多个号码</param>

/// <param name="MsgContent">短信内容</param>

/// <param name="SequenceId">序列号</param>

/// <param name="Service_Id">业务代码</param>

/// <param name="FeeType">资费类别</param>

/// <param name="FeeCode">资费代码(以分为单位)</param>

/// <param name="Src_Id">源号码</param>

/// <param name="LinkId"></param>

public void Submit(ulong MsgId, string FeeTerminalId, string[] DestTerminalId, string MsgContent, uint SequenceId, string Service_Id, string FeeType, string FeeCode, string Src_Id, string WapURL)

{

Submit(MsgId, 1, 0, FeeTerminalId, DestTerminalId, MsgContent, SequenceId, Service_Id, FeeType, FeeCode, Src_Id, WapURL);

}

/// <summary>

/// 发送短信

/// </summary>

/// <param name="MsgId">信息标识</param>

/// <param name="RegisteredDelivery">是否要返回状态确认报告</param>

/// <param name="Fee_UserType">计费用户类型</param>

/// <param name="FeeTerminalId">被计费用户的号码</param>

/// <param name="DestTerminalId">接收短信的MSISDN号码_多个号码</param>

/// <param name="MsgContent">短信内容</param>

/// <param name="SequenceId">序列号</param>

/// <param name="Service_Id">业务代码</param>

/// <param name="FeeType">资费类别</param>

/// <param name="FeeCode">资费代码(以分为单位)</param>

/// <param name="Src_Id">源号码</param>

/// <param name="LinkID"></param>

public void Submit(ulong MsgId, uint RegisteredDelivery, uint Fee_UserType, string FeeTerminalId, string[] DestTerminalId, string MsgContent, uint SequenceId, string Service_Id, string FeeType, string FeeCode, string Src_Id, string WapURL)

{

//这里的字段根据需要设定

CMPP_SUBMIT submit = new CMPP_SUBMIT(SequenceId);

submit.WapURL = WapURL;

submit.Msg_Id = MsgId; // uint _Msg_Id; // 8 Unsigned Integer 信息标识。

submit.Pk_total = 1; // uint _Pk_total; // 1 Unsigned Integer 相同Msg_Id的信息总条数,从1开始。

submit.Pk_number = 1; // uint _Pk_number; // 1 Unsigned Integer 相同Msg_Id的信息序号,从1开始。

submit.Registered_Delivery = RegisteredDelivery; // uint _Registered_Delivery; // 1 Unsigned Integer 是否要求返回状态确认报告:

// // 0:不需要;

// // 1:需要。

submit.Msg_level = 1; // uint _Msg_level; // 1 Unsigned Integer 信息级别。

submit.Service_Id = Service_Id; // string _Service_Id; // 10 Octet String 业务标识,是数字、字母和符号的组合。

submit.Fee_UserType = Fee_UserType; // uint _Fee_UserType; // 1 Unsigned Integer 计费用户类型字段:

// // 0:对目的终端MSISDN计费;

// // 1:对源终端MSISDN计费;

// // 2:对SP计费;

// // 3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。

submit.Fee_terminal_Id = ""; // string _Fee_terminal_Id; // 21 Octet String 被计费用户的号码,当Fee_UserType为3时该值有效,当Fee_UserType为0、1、2时该值无意义。

submit.TP_pId = 0; // uint _TP_pId; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9。

submit.TP_udhi = 0; // uint _TP_udhi; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

submit.Msg_Fmt = 15; // uint _Msg_Fmt; // 1 Unsigned Integer 信息格式:

// // 0:ASCII串;

// // 3:短信写卡操作;

// // 4:二进制信息;

// // 8:UCS2编码;

// // 15:含GB汉字......

submit.Msg_src = this._Source_Addr; // string _Msg_src; // 6 Octet String 信息内容来源(SP_Id)。

submit.FeeType = FeeType; // string _FeeType; // 2 Octet String 资费类别:

// // 01:对"计费用户号码"免费;

// // 02:对"计费用户号码"按条计信息费;

// // 03:对"计费用户号码"按包月收取信息费。

submit.FeeCode = FeeCode; // string _FeeCode; // 6 Octet String 资费代码(以分为单位)。

submit.ValId_Time = "";// Util.Get_MMDDHHMMSS_String(DateTime.Now.AddHours(2)) + "032+"; // string _ValId_Time; // 17 Octet String 存活有效期,格式遵循SMPP3.3协议。

submit.At_Time = "";// Util.Get_MMDDHHMMSS_String(DateTime.Now) + "032+"; // string _At_Time; // 17 Octet String 定时发送时间,格式遵循SMPP3.3协议。

//spnum

submit.Src_Id = Src_Id; // string _Src_Id; // 21 Octet String 源号码。SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,该号码最终在用户手机上显示为短消息的主叫号码。

submit.Dest_terminal_Id = DestTerminalId; //new string[] {"1391xxx1138", "1391xxx1137"}; // string[] _Dest_terminal_Id; // 32*DestUsr_tl Octet String 接收短信的MSISDN号码。

submit.DestUsr_tl = (uint)submit.Dest_terminal_Id.Length; // uint _DestUsr_tl; // 1 Unsigned Integer 接收信息的用户数量(小于100个用户)。

submit.Msg_Fmt = 15; // uint _Msg_Length; // 1 Unsigned Integer 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节),取值大于或等于0。

submit.Msg_Content = MsgContent; //"大家好!这是一个短信群发测试!"; // string _Msg_Content; // Msg_length Octet String 信息内容。

submit.Reserve = ""; // string _LinkID; // 20 Octet String 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段。

this.WriteToStreamWithLock(submit.ToBytes(), this._NetworkStream);

}

public void StartRun()

{

try

{

if (this._ReadResponseThread == null)

{

this._ReadResponseThread = new Thread(new ThreadStart(this.Run));

}

if (this._ReadResponseThread.ThreadState == ThreadState.Unstarted)

{

OnThreadState(ThreadState.Running);

this._ReadResponseThread.Start();

}

else if (this._ReadResponseThread.ThreadState == ThreadState.Suspended)

{

OnThreadState(ThreadState.Running);

this._ReadResponseThread.Resume();

}

else if (this._ReadResponseThread.ThreadState == ThreadState.Stopped)

{

OnThreadState(ThreadState.Running);

this._ReadResponseThread = null;

this._ReadResponseThread = new Thread(new ThreadStart(this.Run));

this._ReadResponseThread.Start();

}

}

catch (Exception ex) {

OnError("CMPPClient启动错误:" + ex.Message);

}

}

/// <summary>

/// 暂停线程

/// </summary>

public void Suspend()

{

try

{

if (this._ReadResponseThread != null && _ReadResponseThread.ThreadState != ThreadState.Stopped && _ReadResponseThread.ThreadState != ThreadState.Suspended)

{

OnThreadState(ThreadState.Suspended);

this._ReadResponseThread.Suspend();

}

}

catch (Exception) { }

}

/// <summary>

/// 停止接收数据

/// </summary>

public void StopReceive()

{

_syncEvents.ExitThreadEvent.Set();

}

/// <summary>

/// 退出

/// </summary>

public void Exit()

{

try

{

StopReceive();

this._NetworkStream.Close();

this._NetworkStream = null;

}

catch (Exception) { }

}

/// <summary>

/// 是否已经停止

/// </summary>

/// <returns></returns>

public bool IsStop()

{

if (_ReadResponseThread == null || _ReadResponseThread.ThreadState == ThreadState.Stopped || _ReadResponseThread.ThreadState == ThreadState.Aborted || _ReadResponseThread.ThreadState == ThreadState.AbortRequested)

return true;

return false;

}

/// <summary>

/// 立刻停止

/// </summary>

/// <returns></returns>

public void StopImmediately()

{

try

{

if (_ReadResponseThread != null)

_ReadResponseThread.Abort();

}

catch (ThreadAbortException) { }

catch (Exception) { }

finally

{

OnThreadState(ThreadState.Stopped);

}

}

#endregion

#region private method

///// <summary>

///// 发送数据通知

///// </summary>

///// <param name="data"></param>

//private void OnCMPPSend(byte[] data)

//{

// if (CMPPSendEvent != null)

// {

// CMPPSendEvent(this, new MessageEventArgs(data));

// }

//}

///// <summary>

///// 接受数据通知

///// </summary>

///// <param name="data"></param>

//private void OnCMPPReceive(byte[] data)

//{

// if (CMPPReceiveEvent != null)

// {

// CMPPReceiveEvent(this, new MessageEventArgs(data));

// }

//}

/// <summary>

/// 信息通知

/// </summary>

private void OnMsg(string msg)

{

if (MsgEvent != null)

{

MsgEvent(msg);

}

}

/// <summary>

/// 错误通知

/// </summary>

/// <param name="type"></param>

/// <param name="err"></param>

private void OnError(string err)

{

if (ErrorEvent != null)

{

ErrorEvent(err);

}

}

/// <summary>

/// 退出

/// </summary>

protected void OnThreadState(ThreadState state)

{

if (ThreadStateEvent != null)

{

ThreadStateEvent(this, state);

}

}

/// <summary>

/// 写入流

/// </summary>

/// <param name="data"></param>

/// <param name="Stream"></param>

private void WriteToStreamWithLock(byte[] data, NetworkStream Stream)

{

// this.OnCMPPSend(data);

try

{

lock (_SyncLockObject)

{

Util.WriteToStream(data, Stream);

}

}

catch (Exception ex)

{

IsConnected = false;

OnError(ex.Message);

}

}

/// <summary>

/// 读取流

/// </summary>

/// <param name="Length"></param>

/// <param name="Stream"></param>

/// <returns></returns>

private byte[] ReadFromStreamWithLock(int Length, NetworkStream Stream)

{

try

{

lock (_SyncLockObject)

{

return Util.ReadFromStream(Length, Stream);

}

}

catch (Exception ex)

{

IsConnected = false;

OnError(ex.Message);

}

return null;

}

/// <summary>

///

/// </summary>

/// <param name="BreakFlag"></param>

private void Run()

{

try

{

while (!_syncEvents.ExitThreadEvent.WaitOne(2, false))

{

if (this._NetworkStream.CanRead)

{

if (this._NetworkStream.DataAvailable)

{

byte[] buffer = new byte[MessageHeader.Length]; //Header

buffer = this.ReadFromStreamWithLock(MessageHeader.Length, this._NetworkStream);

MessageHeader header = new MessageHeader(buffer);

byte[] bytes = new byte[header.Total_Length];

Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

int l = (int)header.Total_Length - MessageHeader.Length;

if (l > 0)

{

buffer = this.ReadFromStreamWithLock(l, this._NetworkStream);

Buffer.BlockCopy(buffer, 0, bytes, MessageHeader.Length, buffer.Length);

}

lock (((ICollection)_receiveQueue).SyncRoot)

{

_receiveQueue.Enqueue(bytes);

}

_syncEvents.NewItemEvent.Set();

}

}

}

}

catch (Exception ex)

{

IsConnected = false;

OnError("CMPPClient接收错误:"+ex.Message);

}

OnThreadState(ThreadState.Stopped);

}

#endregion

}

}

//------------------------------------------------------------------------------

文件 CMPPMessages.cs

//------------------------------------------------------------------------------

using System;

using System.Text;

using System.Security.Cryptography;

namespace AsiaINFO.SMS.CMPP2

{

//CMPP 消息定义

public enum CMPP_Command_Id : uint

{

CMPP_CONNECT = 0x00000001 //请求连接

,

CMPP_CONNECT_RESP = 0x80000001 //请求连接应答

,

CMPP_TERMINATE = 0x00000002 //终止连接

,

CMPP_TERMINATE_RESP = 0x80000002 //终止连接应答

,

CMPP_SUBMIT = 0x00000004 //提交短信

,

CMPP_SUBMIT_RESP = 0x80000004 //提交短信应答

,

CMPP_DELIVER = 0x00000005 //短信下发

,

CMPP_DELIVER_RESP = 0x80000005 //下发短信应答

,

CMPP_QUERY = 0x00000006 //发送短信状态查询

,

CMPP_QUERY_RESP = 0x80000006 //发送短信状态查询应答

,

CMPP_CANCEL = 0x00000007 //删除短信

,

CMPP_CANCEL_RESP = 0x80000007 //删除短信应答

,

CMPP_ACTIVE_TEST = 0x00000008 //激活测试

,

CMPP_ACTIVE_TEST_RESP = 0x80000008 //激活测试应答

,

CMPP_FWD = 0x00000009 //消息前转

,

CMPP_FWD_RESP = 0x80000009 //消息前转应答

,

CMPP_MT_ROUTE = 0x00000010 //MT路由请求

,

CMPP_MT_ROUTE_RESP = 0x80000010 //MT路由请求应答

,

CMPP_MO_ROUTE = 0x00000011 //MO路由请求

,

CMPP_MO_ROUTE_RESP = 0x80000011 //MO路由请求应答

,

CMPP_GET_MT_ROUTE = 0x00000012 //获取MT路由请求

,

CMPP_GET_MT_ROUTE_RESP = 0x80000012 //获取MT路由请求应答

,

CMPP_MT_ROUTE_UPDATE = 0x00000013 //MT路由更新

,

CMPP_MT_ROUTE_UPDATE_RESP = 0x80000013 //MT路由更新应答

,

CMPP_MO_ROUTE_UPDATE = 0x00000014 //MO路由更新

,

CMPP_MO_ROUTE_UPDATE_RESP = 0x80000014 //MO路由更新应答

,

CMPP_PUSH_MT_ROUTE_UPDATE = 0x00000015 //MT路由更新

,

CMPP_PUSH_MT_ROUTE_UPDATE_RESP = 0x80000015 //MT路由更新应答

,

CMPP_PUSH_MO_ROUTE_UPDATE = 0x00000016 //MO路由更新

,

CMPP_PUSH_MO_ROUTE_UPDATE_RESP = 0x80000016 //MO路由更新应答

,

CMPP_GET_MO_ROUTE = 0x00000017 //获取MO路由请求

, CMPP_GET_MO_ROUTE_RESP = 0x80000017 //获取MO路由请求应答

}

/// <summary>

/// 消息头

/// </summary>

public class MessageHeader

{

public const int Length = 4 + 4 + 4;

public CMPP_Command_Id Command_Id

{

get

{

return this._Command_Id;

}

}

public uint Sequence_Id

{

get

{

return this._Sequence_Id;

}

}

public uint Total_Length

{

get

{

return this._Total_Length;

}

}

private uint _Total_Length; // 4 Unsigned Integer 消息总长度(含消息头及消息体)

private CMPP_Command_Id _Command_Id; // 4 Unsigned Integer 命令或响应类型

private uint _Sequence_Id; // 4 Unsigned Integer 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)

public MessageHeader

(

uint Total_Length

, CMPP_Command_Id Command_Id

, uint Sequence_Id

) //发送前

{

this._Total_Length = Total_Length;

this._Command_Id = Command_Id;

this._Sequence_Id = Sequence_Id;

}

public MessageHeader(byte[] bytes)

{

byte[] buffer = new byte[4];

Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._Total_Length = BitConverter.ToUInt32(buffer, 0);

Buffer.BlockCopy(bytes, 4, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._Command_Id = (CMPP_Command_Id)BitConverter.ToUInt32(buffer, 0);

Buffer.BlockCopy(bytes, 8, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._Sequence_Id = BitConverter.ToUInt32(buffer, 0);

}

public byte[] ToBytes()

{

byte[] bytes = new byte[MessageHeader.Length];

byte[] buffer = BitConverter.GetBytes(this._Total_Length);

Array.Reverse(buffer);

Buffer.BlockCopy(buffer, 0, bytes, 0, 4);

buffer = BitConverter.GetBytes((uint)this._Command_Id);

Array.Reverse(buffer);

Buffer.BlockCopy(buffer, 0, bytes, 4, 4);

buffer = BitConverter.GetBytes(this._Sequence_Id);

Array.Reverse(buffer);

Buffer.BlockCopy(buffer, 0, bytes, 8, 4);

return bytes;

}

public override string ToString()

{

return string.Format("MessageHeader: tCommand_Id={0} tSequence_Id={1} tTotal_Length={2}"

, this._Command_Id

, this._Sequence_Id

, this._Total_Length

);

}

}

public class CMPP_CONNECT //: CMPP_Request

{

public const int BodyLength = 6 + 16 + 1 + 4;

private string _Source_Addr; // 6 Octet String 源地址,此处为SP_Id,即SP的企业代码。

private string _Password;

private byte[] _AuthenticatorSource; // 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:

// AuthenticatorSource =

// MD5(Source_Addr+9 字节的0 +shared secret+timestamp)

// Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。

private uint _Version; // 1 Unsigned Integer 双方协商的版本号(高位4bit表示主版本号,低位4bit表示次版本号),对于3.0的版本,高4bit为3,低4位为0

private uint _Timestamp; // 4 Unsigned Integer 时间戳的明文,由客户端产生,格式为MMDDHHMMSS,即月日时分秒,10位数字的整型,右对齐 。

private MessageHeader _Header;

public MessageHeader Header

{

get

{

return this._Header;

}

}

public byte[] AuthenticatorSource

{

get

{

return this._AuthenticatorSource;

}

}

public CMPP_CONNECT

(

string Source_Addr

, string Password

, DateTime Timestamp

, uint Version

, uint Sequence_Id

)

{

this._Header = new MessageHeader(MessageHeader.Length + BodyLength, CMPP_Command_Id.CMPP_CONNECT, Sequence_Id);

this._Source_Addr = Source_Addr;

this._Password = Password;

string s = Util.Get_MMDDHHMMSS_String(Timestamp);

this._Timestamp = UInt32.Parse(s);

//byte[] buffer = new byte[6 + 9 + this._Password.Length + 10];

//Encoding.ASCII.GetBytes(this._Source_Addr).CopyTo(buffer, 0);

//Encoding.ASCII.GetBytes(this._Password).CopyTo(buffer, 6 + 9);

//Encoding.ASCII.GetBytes(s).CopyTo(buffer, 6 + 9 + this._Password.Length);

//this._AuthenticatorSource = new MD5CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length);

byte[] clientid = System.Text.Encoding.ASCII.GetBytes(Source_Addr);

byte[] password = System.Text.Encoding.ASCII.GetBytes(Password);

byte[] timestamp = System.Text.Encoding.ASCII.GetBytes(s);

byte[] data = new byte[clientid.Length + 9 + password.Length + timestamp.Length];

Array.Copy(clientid, data, clientid.Length);

Array.Copy(password, 0, data, clientid.Length + 9, password.Length);

Array.Copy(timestamp, 0, data, clientid.Length + 9 + password.Length, timestamp.Length);

System.Security.Cryptography.MD5 MD5 = new System.Security.Cryptography.MD5CryptoServiceProvider();

_AuthenticatorSource = MD5.ComputeHash(data);

this._Version = Version;

}

public byte[] ToBytes()

{

int i = 0;

byte[] bytes = new byte[MessageHeader.Length + BodyLength];

//header 12

byte[] buffer = this._Header.ToBytes();

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

//Source_Addr 6

i += MessageHeader.Length;

buffer = Encoding.ASCII.GetBytes(this._Source_Addr);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

//AuthenticatorSource 16

i += 6;

buffer = this._AuthenticatorSource;

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //16

//version 1

i += 16;

bytes[i++] = (byte)this._Version; //版本

//Timestamp

buffer = BitConverter.GetBytes(this._Timestamp);

Array.Reverse(buffer);

buffer.CopyTo(bytes, i);

return (bytes);

}

public override string ToString()

{

return string.Format("Header={0} AuthenticatorSource={1} Password={2} Source_Addr={3} Timestamp={4} Version={5}"

, this._Header.ToString()

, this._AuthenticatorSource

, this._Password

, this._Source_Addr

, this._Timestamp

, this._Version);

}

}

public class CMPP_CONNECT_RESP //: CMPP_Response

{

private MessageHeader _Header;

public const int BodyLength = 4 + 16 + 1;

private uint _Status; // 4 Unsigned Integer 状态

// 0:正确

// 1:消息结构错

// 2:非法源地址

// 3:认证错

// 4:版本太高

// 5~:其他错误

private byte[] _AuthenticatorISMG; // 16 Octet String ISMG认证码,用于鉴别ISMG。

// 其值通过单向MD5 hash计算得出,表示如下:

// AuthenticatorISMG =MD5(Status+AuthenticatorSource+shared secret),Shared secret 由中国移动与源地址实体事先商定,AuthenticatorSource为源地址实体发送给ISMG的对应消息CMPP_Connect中的值。

// 认证出错时,此项为空。

private uint _Version; // 1 Unsigned Integer 服务器支持的最高版本号,对于3.0的版本,高4bit为3,低4位为0

public byte[] AuthenticatorISMG

{

get

{

return this._AuthenticatorISMG;

}

}

public uint Status

{

get

{

return this._Status;

}

}

public uint Version

{

get

{

return this._Version;

}

}

public MessageHeader Header

{

get

{

return this._Header;

}

}

public CMPP_CONNECT_RESP(byte[] bytes)

{

//header 12

int i = 0;

byte[] buffer = new byte[MessageHeader.Length];

Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

this._Header = new MessageHeader(buffer);

//status 4

i += MessageHeader.Length;

this._Status = bytes[i];

//AuthenticatorISMG 16

i += 1;

this._AuthenticatorISMG = new byte[16];

Buffer.BlockCopy(bytes, MessageHeader.Length + 1, this._AuthenticatorISMG, 0, this._AuthenticatorISMG.Length);

//version

i += 16;

this._Version = bytes[i];

}

public override string ToString()

{

return string.Format("Header={0} AuthenticatorISMG={1} BodyLength={2} Status={3} Version={4}"

, this._Header.ToString()

, this._AuthenticatorISMG

, CMPP_CONNECT_RESP.BodyLength

, this._Status

, this._Version);

}

}

public class CMPP_SUBMIT //: CMPP_Request

{

private int _BodyLength;

//without _Dest_terminal_Id Msg_Content

public const int FixedBodyLength = 8

+ 1

+ 1

+ 1

+ 1

+ 10

+ 1

+ 21

+ 1

+ 1

+ 1

+ 6

+ 2

+ 6

+ 17

+ 17

+ 21

+ 1

//+ 21*DestUsr_tl

+ 1

//+ Msg_length

+ 8;

private ulong _Msg_Id; // 8 Unsigned Integer 信息标识。

private uint _Pk_total; // 1 Unsigned Integer 相同Msg_Id的信息总条数,从1开始。

private uint _Pk_number; // 1 Unsigned Integer 相同Msg_Id的信息序号,从1开始。

private uint _Registered_Delivery; // 1 Unsigned Integer 是否要求返回状态确认报告:

// 0:不需要;

// 1:需要。

private uint _Msg_level; // 1 Unsigned Integer 信息级别。

private string _Service_Id; // 10 Octet String 业务标识,是数字、字母和符号的组合。

private uint _Fee_UserType; // 1 Unsigned Integer 计费用户类型字段:

// 0:对目的终端MSISDN计费;

// 1:对源终端MSISDN计费;

// 2:对SP计费;

// 3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。

private string _Fee_terminal_Id; // 21 Octet String 被计费用户的号码,当Fee_UserType为3时该值有效,当Fee_UserType为0、1、2时该值无意义。

private uint _TP_pId; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9。

private uint _TP_udhi; // 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

private uint _Msg_Fmt; // 1 Unsigned Integer 信息格式:

// 0:ASCII串;

// 3:短信写卡操作;

// 4:二进制信息;

// 8:UCS2编码;

// 15:含GB汉字......

private string _Msg_src; // 6 Octet String 信息内容来源(SP_Id)。

private string _FeeType; // 2 Octet String 资费类别:

// 01:对"计费用户号码"免费;

// 02:对"计费用户号码"按条计信息费;

// 03:对"计费用户号码"按包月收取信息费。

private string _FeeCode; // 6 Octet String 资费代码(以分为单位)。

private string _ValId_Time; // 17 Octet String 存活有效期,格式遵循SMPP3.3协议。

private string _At_Time; // 17 Octet String 定时发送时间,格式遵循SMPP3.3协议。

private string _Src_Id; // 21 Octet String 源号码。SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,该号码最终在用户手机上显示为短消息的主叫号码。

private uint _DestUsr_tl; // 1 Unsigned Integer 接收信息的用户数量(小于100个用户)。

private string[] _Dest_terminal_Id; // 32*DestUsr_tl Octet String 接收短信的MSISDN号码。

private uint _Msg_Length; // 1 Unsigned Integer 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节),取值大于或等于0。

private string _Msg_Content; // Msg_length Octet String 信息内容。

private string _Reserve; // 8 Octet String 保留

private string _WapURL = ""; //WAPPUSH

public string WapURL

{

get { return _WapURL; }

set { _WapURL = value; }

}

public MessageHeader Header

{

get

{

return _Header;

}

set

{

_Header = value;

}

}

private MessageHeader _Header;

private uint _Sequence_Id;

public CMPP_SUBMIT(uint Sequence_Id)

{

this._Sequence_Id = Sequence_Id;

}

private byte[] _Msg_Content_Bytes;

private void SetHeader()

{

if (string.IsNullOrEmpty(_WapURL))

{

//byte[] buf;

switch (this._Msg_Fmt)

{

case 8:

_Msg_Content_Bytes = Encoding.BigEndianUnicode.GetBytes(this._Msg_Content);

break;

case 15: //gb2312

_Msg_Content_Bytes = Encoding.GetEncoding("gb2312").GetBytes(this._Msg_Content);

break;

case 0: //ascii

case 3: //短信写卡操作

case 4: //二进制信息

default:

_Msg_Content_Bytes = Encoding.ASCII.GetBytes(this._Msg_Content);

break;

}

}

else

{

_Msg_Content_Bytes = WapPush.GetInstance().toBytes(this._Msg_Content, this._WapURL);

this._Msg_Fmt = 0x04;

this.TP_pId = 1;

this.TP_udhi = 1;

}

this._Msg_Length = (uint)_Msg_Content_Bytes.Length;

this._BodyLength = (int)(FixedBodyLength + 21 * this._Dest_terminal_Id.Length + this._Msg_Length);

this._Header = new MessageHeader((uint)(MessageHeader.Length + this._BodyLength), CMPP_Command_Id.CMPP_SUBMIT, this._Sequence_Id);

}

public byte[] ToBytes()

{

//Msg_Length Msg_Content

int i = 0;

byte[] bytes = new byte[MessageHeader.Length + this._BodyLength];

byte[] buffer = this._Header.ToBytes();

Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

i += MessageHeader.Length;

//Msg_Id //8

buffer = new byte[8];

buffer = BitConverter.GetBytes(this._Msg_Id);

Array.Reverse(buffer);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //10

//_Pk_total

i += 8;

bytes[i++] = (byte)this._Pk_total;

bytes[i++] = (byte)this._Pk_number;

bytes[i++] = (byte)this._Registered_Delivery;

bytes[i++] = (byte)this._Msg_level;

//Service_Id

buffer = Encoding.ASCII.GetBytes(this._Service_Id);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //10

//Fee_UserType

i += 10;

bytes[i++] = (byte)this._Fee_UserType;

//Fee_terminal_Id

buffer = Encoding.ASCII.GetBytes(this._Fee_terminal_Id);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21

//Fee_terminal_type

i += 21;

bytes[i++] = (byte)this._TP_pId;

bytes[i++] = (byte)this._TP_udhi;

bytes[i++] = (byte)this._Msg_Fmt;

//Msg_src

buffer = Encoding.ASCII.GetBytes(this._Msg_src);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6

//FeeType

i += 6;

buffer = Encoding.ASCII.GetBytes(this._FeeType);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //2

//FeeCode

i += 2;

buffer = Encoding.ASCII.GetBytes(this._FeeCode);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6

//ValId_Time

i += 6;

buffer = Encoding.ASCII.GetBytes(this._ValId_Time);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17

//At_Time

i += 17;

buffer = Encoding.ASCII.GetBytes(this._At_Time);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17

//Src_Id

i += 17;

buffer = Encoding.ASCII.GetBytes(this._Src_Id);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21

//DestUsr_tl

i += 21;

this._DestUsr_tl = (uint)this._Dest_terminal_Id.Length;

bytes[i++] = (byte)this._DestUsr_tl;

//Dest_terminal_Id

foreach (string s in this._Dest_terminal_Id)

{

buffer = Encoding.ASCII.GetBytes(s);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

i += 21;

}

//Msg_Length

bytes[i++] = (byte)this._Msg_Length;

//Msg_Content

//buffer = Encoding.

Buffer.BlockCopy(this._Msg_Content_Bytes, 0, bytes, i, this._Msg_Content_Bytes.Length);

//Reserve 8

i += (int)this._Msg_Length;

buffer = Encoding.ASCII.GetBytes(this._Reserve);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

return bytes;

}

public ulong Msg_Id

{

get

{

return this._Msg_Id;

}

set

{

this._Msg_Id = value;

}

}

public uint Pk_total

{

get

{

return this._Pk_total;

}

set

{

this._Pk_total = value;

}

}

public uint Pk_number

{

get

{

return this._Pk_number;

}

set

{

this._Pk_number = value;

}

}

public uint Registered_Delivery

{

get

{

return this._Registered_Delivery;

}

set

{

this._Registered_Delivery = value;

}

}

public uint Msg_level

{

get

{

return this._Msg_level;

}

set

{

this._Msg_level = value;

}

}

public string Service_Id

{

get

{

return this._Service_Id;

}

set

{

this._Service_Id = value;

}

}

public uint Fee_UserType

{

get

{

return this._Fee_UserType;

}

set

{

this._Fee_UserType = value;

}

}

public string Fee_terminal_Id

{

get

{

return this._Fee_terminal_Id;

}

set

{

this._Fee_terminal_Id = value;

}

}

public uint TP_pId

{

get

{

return this._TP_pId;

}

set

{

this._TP_pId = value;

}

}

public uint TP_udhi

{

get

{

return this._TP_udhi;

}

set

{

this._TP_udhi = value;

}

}

public uint Msg_Fmt

{

get

{

return this._Msg_Fmt;

}

set

{

this._Msg_Fmt = value;

if (this._Msg_Content != null)

{

this.SetHeader();

}

}

}

public string Msg_src

{

get

{

return this._Msg_src;

}

set

{

_Msg_src = value;

}

}

public string FeeType

{

get

{

return this._FeeType;

}

set

{

this._FeeType = value;

}

}

public string FeeCode

{

get

{

return this._FeeCode;

}

set

{

this._FeeCode = value;

}

}

public string ValId_Time

{

get

{

return this._ValId_Time;

}

set

{

this._ValId_Time = value;

}

}

public string At_Time

{

get

{

return this._At_Time;

}

set

{

this._At_Time = value;

}

}

public string Src_Id

{

get

{

return this._Src_Id;

}

set

{

this._Src_Id = value;

}

}

public uint DestUsr_tl

{

get

{

return this._DestUsr_tl;

}

set

{

this._DestUsr_tl = value;

}

}

public string[] Dest_terminal_Id

{

get

{

return this._Dest_terminal_Id;

}

set

{

this._Dest_terminal_Id = value;

}

}

public uint Msg_Length

{

get

{

return this._Msg_Length;

}

set

{

this._Msg_Length = value;

}

}

public string Msg_Content

{

get

{

return this._Msg_Content;

}

set

{

this._Msg_Content = value;

this.SetHeader();

}

}

public string Reserve

{

get

{

return this._Reserve;

}

set

{

this._Reserve = value;

}

}

public override string ToString()

{

return "[/r/n"

+ this._Header.ToString() + "/r/n"

+ string.Format

(

"/tMessageBody:"

+ "/r/n/t/tAt_Time: {0}"

+ "/r/n/t/tBodyLength: {1}"

+ "/r/n/t/tDest_terminal_Id: {2}"

+ "/r/n/t/tDestUsr_tl: {3}"

+ "/r/n/t/tFee_terminal_Id: {4}"

+ "/r/n/t/tFee_UserType: {5}"

+ "/r/n/t/tFeeCode: {6}"

+ "/r/n/t/tFeeType: {7}"

+ "/r/n/t/tReserve: {8}"

+ "/r/n/t/tMsg_Content: {9}"

+ "/r/n/t/tMsg_Fmt: {10}"

+ "/r/n/t/tMsg_Id: {11}"

+ "/r/n/t/tMsg_Length: {12}"

+ "/r/n/t/tMsg_level: {13}"

+ "/r/n/t/tMsg_src: {14}"

+ "/r/n/t/tPk_number: {15}"

+ "/r/n/t/tPk_total: {16}"

+ "/r/n/t/tRegistered_Delivery: {17}"

+ "/r/n/t/tSequence_Id: {18}"

+ "/r/n/t/tService_Id: {19}"

+ "/r/n/t/tSrc_Id: {20}"

+ "/r/n/t/tTP_pId: {21}"

+ "/r/n/t/tTP_udhi: {22}"

+ "/r/n/t/tValId_Time: {23}"

, this._At_Time

, this._BodyLength

, String.Join(",", this._Dest_terminal_Id)

, this._DestUsr_tl

, this._Fee_terminal_Id

, this._Fee_UserType

, this._FeeCode

, this._FeeType

, this._Reserve

, this._Msg_Content

, this._Msg_Fmt

, this._Msg_Id

, this._Msg_Length

, this._Msg_level

, this._Msg_src

, this._Pk_number

, this._Pk_total

, this._Registered_Delivery

, this._Sequence_Id

, this._Service_Id

, this._Src_Id

, this._TP_pId

, this._TP_udhi

, this._ValId_Time

)

+ "/r/n]";

}

}

public class CMPP_SUBMIT_RESP //: CMPP_Response

{

private MessageHeader _Header;

// private ulong _Msg_Id;

private string _Msg_Id;

private uint _Result;

public const int BodyLength = 8 + 1;

public string Msg_Id

{

get

{

return this._Msg_Id;

}

}

public uint Result

{

get

{

return this._Result;

}

}

public MessageHeader Header

{

get

{

return this._Header;

}

}

public CMPP_SUBMIT_RESP(byte[] bytes)

{

int i = 0;

byte[] buffer = new byte[MessageHeader.Length];

Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

this._Header = new MessageHeader(buffer);

//Msg_Id

i += MessageHeader.Length;

buffer = new byte[8];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Msg_Id = System.BitConverter.ToString(buffer);

//string test = System.BitConverter.ToString(buffer);

//System.Console.WriteLine("CMPP_SUBMIT_RESP Msg_Id=" + test);

//Array.Reverse(buffer);

//this._Msg_Id = BitConverter.ToUInt64(buffer, 0);

//Result

i += 8;

this._Result = (uint)bytes[i++];

//buffer = new byte[1];

//Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

//Array.Reverse(buffer);

//this._Result = BitConverter.ToUInt32(buffer, 0);

}

public override string ToString()

{

return "[/r/n"

+ this._Header.ToString() + "/r/n"

+ string.Format

(

"/tMessageBody:"

+ "/r/n/t/tMsg_Id: {0}"

+ "/r/n/t/tResult: {1}"

, this._Msg_Id

, this._Result

)

+ "/r/n]";

}

}

public class CMPP_DELIVER //: CMPP_Request

{

public ulong Msg_Id

{

get

{

return _Msg_Id;

}

}

public string Dest_Id

{

get

{

return _Dest_Id;

}

}

public string Service_Id

{

get

{

return _Service_Id;

}

}

public uint TP_pid

{

get

{

return _TP_pid;

}

}

public uint TP_udhi

{

get

{

return _TP_udhi;

}

}

public uint Msg_Fmt

{

get

{

return _Msg_Fmt;

}

}

public string Src_terminal_Id

{

get

{

return _Src_terminal_Id;

}

}

public uint Registered_Delivery

{

get

{

return _Registered_Delivery;

}

}

public uint Msg_Length

{

get

{

return _Msg_Length;

}

}

public string Msg_Content

{

get

{

return _Msg_Content;

}

}

public string Reserved

{

get

{

return _Reserved;

}

}

/// <summary>

/// 状态报告

/// </summary>

public byte[] Report

{

get { return _Report; }

}

private ulong _Msg_Id; // 8 Unsigned Integer 信息标识。

// 生成算法如下:

// 采用64位(8字节)的整数:

// (1)????????? 时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,其中

// bit64~bit61:月份的二进制表示;

// bit60~bit56:日的二进制表示;

// bit55~bit51:小时的二进制表示;

// bit50~bit45:分的二进制表示;

// bit44~bit39:秒的二进制表示;

// (2)????????? 短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中;

// (3)????????? 序列号:bit16~bit1,顺序增加,步长为1,循环使用。

// 各部分如不能填满,左补零,右对齐。

private string _Dest_Id; // 21 Octet String 目的号码。

// SP的服务代码,一般4--6位,或者是前缀为服务代码的长号码;该号码是手机用户短消息的被叫号码。

private string _Service_Id; // 10 Octet String 业务标识,是数字、字母和符号的组合。

private uint _TP_pid; // 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.9。

private uint _TP_udhi; // 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

private uint _Msg_Fmt; // 1 Unsigned Integer 信息格式:

// 0:ASCII串;

// 3:短信写卡操作;

// 4:二进制信息;

// 8:UCS2编码;

// 15:含GB汉字。

private string _Src_terminal_Id; // 21 Octet String 源终端MSISDN号码(状态报告时填为CMPP_SUBMIT消息的目的终端号码)。

private uint _Registered_Delivery; // 1 Unsigned Integer 是否为状态报告:

// 0:非状态报告;

// 1:状态报告。

private uint _Msg_Length; // 1 Unsigned Integer 消息长度,取值大于或等于0。

private string _Msg_Content; // Msg_length Octet String 消息内容。

private string _Reserved; // 8 Octet String 保留项。

private byte[] _Report;

private MessageHeader _Header;

public MessageHeader Header

{

get

{

return this._Header;

}

}

public const int FixedBodyLength = 8 // Msg_Id Unsigned Integer 信息标识。

// 生成算法如下:

// 采用64位(8字节)的整数:

// (1)????????? 时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,其中

// bit64~bit61:月份的二进制表示;

// bit60~bit56:日的二进制表示;

// bit55~bit51:小时的二进制表示;

// bit50~bit45:分的二进制表示;

// bit44~bit39:秒的二进制表示;

// (2)????????? 短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中;

// (3)????????? 序列号:bit16~bit1,顺序增加,步长为1,循环使用。

// 各部分如不能填满,左补零,右对齐。

+ 21 // Dest_Id Octet String 目的号码。

// SP的服务代码,一般4--6位,或者是前缀为服务代码的长号码;该号码是手机用户短消息的被叫号码。

+ 10 // Service_Id Octet String 业务标识,是数字、字母和符号的组合。

+ 1 // TP_pid Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.9。

+ 1 // TP_udhi Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐。

+ 1 // Msg_Fmt Unsigned Integer 信息格式:

// 0:ASCII串;

// 3:短信写卡操作;

// 4:二进制信息;

// 8:UCS2编码;

// 15:含GB汉字。

+ 32 // Src_terminal_Id Octet String 源终端MSISDN号码(状态报告时填为CMPP_SUBMIT消息的目的终端号码)。

+ 1 // Src_terminal_type Unsigned Integer 源终端号码类型,0:真实号码;1:伪码。

+ 1 // Registered_Delivery Unsigned Integer 是否为状态报告:

// 0:非状态报告;

// 1:状态报告。

+ 1 // Msg_Length Unsigned Integer 消息长度,取值大于或等于0。

//Msg_length // Msg_Content Octet String 消息内容。

+ 20; // LinkID Octet String 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段。

private int _BodyLength;

public int BodyLength

{

get

{

return this._BodyLength;

}

}

public CMPP_DELIVER(byte[] bytes)

{

int i = 0;

byte[] buffer = new byte[MessageHeader.Length];

Buffer.BlockCopy(bytes, 0, buffer, 0, MessageHeader.Length);

this._Header = new MessageHeader(buffer);

//Msg_Id 8

i += MessageHeader.Length;

buffer = new byte[8];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._Msg_Id = BitConverter.ToUInt64(buffer, 0);

string s = null;

//Dest_Id 21

i += 8;

buffer = new byte[21];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

s = Encoding.ASCII.GetString(buffer).Trim();

if(s.IndexOf('/0')>0)

s = s.Substring(0, s.IndexOf('/0'));

this._Dest_Id = s;

//Service_Id 10

i += 21;

buffer = new byte[10];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

s = Encoding.ASCII.GetString(buffer).Trim();

if(s.IndexOf('/0')>0)

s = s.Substring(0, s.IndexOf('/0'));

this._Service_Id = s;

//TP_pid 1

i += 10;

this._TP_pid = (uint)bytes[i++];

this._TP_udhi = (uint)bytes[i++];

this._Msg_Fmt = (uint)bytes[i++];

//Src_terminal_Id 21

buffer = new byte[21];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

s = Encoding.ASCII.GetString(buffer).Trim();

if(s.IndexOf('/0')>0)

s = s.Substring(0, s.IndexOf('/0'));

if (s != null && s.Length > 11 && s.Substring(0, 2) == "86")

s = s.Substring(2, s.Length - 2);

this._Src_terminal_Id = s;

//Src_terminal_type 1

i += 21;

this._Registered_Delivery = (uint)bytes[i++];

this._Msg_Length = (uint)bytes[i++];

//Msg_Content

buffer = new byte[this._Msg_Length];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

if (this._Registered_Delivery == 1)

{ ///状态报告 保存至Report

this._Msg_Content = "";

this._Report = new byte[_Msg_Length];

Buffer.BlockCopy(buffer, 0, _Report, 0, _Report.Length);

}

else

{

///短信 保存至Msg_Content

switch (this._Msg_Fmt)

{

case 8:

this._Msg_Content = Encoding.BigEndianUnicode.GetString(buffer).Trim();

break;

case 15: //gb2312

this._Msg_Content = Encoding.GetEncoding("gb2312").GetString(buffer).Trim();

break;

case 0: //ascii

case 3: //短信写卡操作

case 4:

//二进制信息

default:

this._Msg_Content = Encoding.ASCII.GetString(buffer).ToString();

break;

}

}

//Reserved 8

i += (int)this._Msg_Length;

buffer = new byte[8];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

s = Encoding.ASCII.GetString(buffer).Trim();

if(s.IndexOf('/0')>0)

s = s.Substring(0, s.IndexOf('/0'));

this._Reserved = s;

}

public byte[] ToBytes()

{ //Msg_Length Msg_Content

byte[] buf;

switch (this._Msg_Fmt)

{

case 8:

buf = Encoding.BigEndianUnicode.GetBytes(this._Msg_Content);

break;

case 15: //gb2312

buf = Encoding.GetEncoding("gb2312").GetBytes(this._Msg_Content);

break;

case 0: //ascii

case 3: //短信写卡操作

case 4:

//二进制信息

default:

buf = Encoding.ASCII.GetBytes(this._Msg_Content);

break;

}

this._Msg_Length = (uint)buf.Length;

this._BodyLength = FixedBodyLength + (int)this._Msg_Length;

byte[] bytes = new byte[MessageHeader.Length + this._BodyLength];

int i = 0;

byte[] buffer = null;

//header 12

this._Header = new MessageHeader((uint)(MessageHeader.Length + this._BodyLength), CMPP_Command_Id.CMPP_DELIVER, 0);

//Msg_Id 8

i += MessageHeader.Length;

buffer = new Byte[8];

buffer = BitConverter.GetBytes(this._Msg_Id);

Array.Reverse(buffer);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

//Dest_Id 21

i += 8;

buffer = new byte[21];

buffer = Encoding.ASCII.GetBytes(this._Dest_Id);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

//Service_Id 10

i += 21;

buffer = new byte[10];

buffer = Encoding.ASCII.GetBytes(this._Service_Id);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

//TP_pid 1

i += 10;

bytes[i++] = (byte)this._TP_pid;

bytes[i++] = (byte)this._TP_udhi;

bytes[i++] = (byte)this._Msg_Fmt;

//Src_terminal_Id 21

buffer = new byte[21];

buffer = Encoding.ASCII.GetBytes(this._Src_terminal_Id);

Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);

//Src_terminal_type 1

i += 21;

bytes[i++] = (byte)this._Registered_Delivery;

bytes[i++] = (byte)this._Msg_Length;

//Msg_Content

Buffer.BlockCopy(buf, 0, bytes, i, buf.Length);

//Reserved

i += (int)this._Msg_Length;

return bytes;

}

public override string ToString()

{

return "[/r/n"

+ this._Header.ToString() + "/r/n"

+ string.Format

(

"/tMessageBody:"

+ "/r/n/t/tBodyLength: {0}"

+ "/r/n/t/tDest_Id: {1}"

+ "/r/n/t/tReserved: {2}"

+ "/r/n/t/tMsg_Content: {3}"

+ "/r/n/t/tMsg_Fmt: {4}"

+ "/r/n/t/tMsg_Id: {5}"

+ "/r/n/t/tMsg_Length: {6}"

+ "/r/n/t/tRegistered_Delivery: {7}"

+ "/r/n/t/tService_Id: {8}"

+ "/r/n/t/tSrc_terminal_Id: {9}"

+ "/r/n/t/tTP_pid: {10}"

+ "/r/n/t/tTP_udhi: {11}"

, this._BodyLength

, this._Dest_Id

, this._Reserved

, this._Msg_Content

, this._Msg_Fmt

, this._Msg_Id

, this._Msg_Length

, this._Registered_Delivery

, this._Service_Id

, this._Src_terminal_Id

, this._TP_pid

, this._TP_udhi

)

+ "/r/n]";

}

}

public class CMPP_DELIVER_RESP //: CMPP_Response

{

private MessageHeader _Header;

private ulong _Msg_Id;

private uint _Result;

public const int Bodylength = 8 + 1;

private uint _Sequence_Id;

public CMPP_DELIVER_RESP(ulong Msg_Id, uint Result, uint Sequence_Id)

{

this._Msg_Id = Msg_Id;

this._Result = Result;

this._Sequence_Id = Sequence_Id;

}

public byte[] ToBytes()

{

int i = 0;

byte[] bytes = new byte[MessageHeader.Length + Bodylength];

byte[] buffer = new byte[MessageHeader.Length];

//header

this._Header = new MessageHeader(MessageHeader.Length + Bodylength, CMPP_Command_Id.CMPP_DELIVER_RESP, _Sequence_Id);

buffer = this._Header.ToBytes();

Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

i += MessageHeader.Length;

//msg_id 8

buffer = BitConverter.GetBytes(this._Msg_Id);

Array.Reverse(buffer);

buffer.CopyTo(bytes, i);

//result 1

i += 8;

bytes[i] = (byte)this._Result;

//buffer = BitConverter.GetBytes(this._Result);

//Array.Reverse(buffer);

//buffer.CopyTo(bytes, i);

return bytes;

}

public override string ToString()

{

return this._Header.ToString() + "/r/n"

+ string.Format

(

"[/r/nMessageBody:"

+ "/r/n/tMsg_Id: {0}"

+ "/r/n/tResult: {1}"

+ "/r/n]"

, this._Msg_Id

, this._Result

);

}

}

public class CMPP_Msg_Content //状态报告

{

public const int BodyLength = 8 + 7 + 10 + 10 + 21 + 4;

private string _Msg_Id; // 8 Unsigned Integer 信息标识。SP提交短信(CMPP_SUBMIT)操作时,与SP相连的ISMG产生的Msg_Id。

private string _Stat; // 7 Octet String 发送短信的应答结果,含义详见表一。SP根据该字段确定CMPP_SUBMIT消息的处理状态。

private string _Submit_time; // 10 Octet String YYMMDDHHMM(YY为年的后两位00-99,MM:01-12,DD:01-31,HH:00-23,MM:00-59)。

private string _Done_time; // 10 Octet String YYMMDDHHMM。

public CMPP_Msg_Content(byte[] bytes)

{

// if (bytes.Length == BodyLength)

if (bytes.Length >=60)

{

int i = 0;

//_Msg_Id 8

byte[] buffer = new byte[8];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Msg_Id = System.BitConverter.ToString(buffer);

//Array.Reverse(buffer);

// this._Msg_Id = BitConverter.ToUInt32(buffer, 0);

//_Stat 7

i += 8;

buffer = new byte[7];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Stat = Encoding.ASCII.GetString(buffer);

//_Submit_time 10

i += 7;

buffer = new byte[10];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Submit_time = Encoding.ASCII.GetString(buffer);

//_Done_time 10

i += 10;

buffer = new byte[10];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Submit_time = Encoding.ASCII.GetString(buffer);

//Dest_terminal_Id 21

i += 10;

buffer = new byte[bytes.Length-i-4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

//this._Dest_terminal_Id = Encoding.ASCII.GetString(buffer);

string s = Encoding.ASCII.GetString(buffer).Trim();

if (s.IndexOf('/0') > 0)

s = s.Substring(0, s.IndexOf('/0'));

if (s != null && s.Length > 11 && s.Substring(0, 2) == "86")

s = s.Substring(2, s.Length - 2);

this._Dest_terminal_Id = s;

//i += 10;

//buffer = new byte[32];

//Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

//this._Dest_terminal_Id = Encoding.ASCII.GetString(buffer);

//SMSC_sequence 4

// i += 21;

i += buffer.Length;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._SMSC_sequence = BitConverter.ToUInt32(buffer, 0);

}

}

public string Msg_Id

{

get

{

return this._Msg_Id;

}

}

public string Stat

{

get

{

return this._Stat;

}

}

public string Submit_time

{

get

{

return this._Submit_time;

}

}

public string Done_time

{

get

{

return this._Done_time;

}

}

public string Dest_terminal_Id

{

get

{

return this._Dest_terminal_Id;

}

}

public uint SMSC_sequence

{

get

{

return this._SMSC_sequence;

}

}

private string _Dest_terminal_Id; // 32 Octet String 目的终端MSISDN号码(SP发送CMPP_SUBMIT消息的目标终端)。

private uint _SMSC_sequence; // 4 Unsigned Integer 取自SMSC发送状态报告的消息体中的消息标识。

public override string ToString()

{

return string.Format

(

"[/r/nMessageBody:"

+ "/r/n/tBodyLength: {0}"

+ "/r/n/tDest_terminal_Id: {1}"

+ "/r/n/tDone_time: {2}"

+ "/r/n/tMsg_Id: {3}"

+ "/r/n/tSMSC_sequence: {4}"

+ "/r/n/tStat: {5}"

+ "/r/n/tSubmit_time: {6}"

+ "/r/n]"

, CMPP_Msg_Content.BodyLength

, this._Dest_terminal_Id

, this._Done_time

, this._Msg_Id

, this._SMSC_sequence

, this._Stat

, this._Submit_time

);

}

}

public class CMPP_QUERY //: CMPP_Request

{

private MessageHeader _Header;

private string _Time; // 8 Octet String 时间YYYYMMDD(精确至日)。

private uint _Query_Type; // 1 Unsigned Integer 查询类别:

// 0:总数查询;

// 1:按业务类型查询。

private string _Query_Code; // 10 Octet String 查询码。

// 当Query_Type为0时,此项无效;当Query_Type为1时,此项填写业务类型Service_Id.。

private string _Reserve; // 8 Octet String 保留。

public MessageHeader Header

{

get

{

return this._Header;

}

}

public string Time

{

get

{

return this._Time;

}

}

public uint Query_Type

{

get

{

return this._Query_Type;

}

}

public string Query_Code

{

get

{

return this._Query_Code;

}

}

public string Reserve

{

get

{

return this._Reserve;

}

}

public const int BodyLength = 8 + 1 + 10 + 8;

public CMPP_QUERY

(

DateTime Time

, uint Query_Type

, string Query_Code

, string Reserve

, uint Sequence_Id

)

{

this._Time = Util.Get_YYYYMMDD_String(Time);

this._Query_Type = Query_Type;

this._Query_Code = Query_Code;

this._Reserve = Reserve;

this._Header = new MessageHeader((uint)(MessageHeader.Length + BodyLength), CMPP_Command_Id.CMPP_QUERY, Sequence_Id);

}

public byte[] ToBytes()

{

int i = 0;

byte[] bytes = new byte[MessageHeader.Length + BodyLength];

//header

byte[] buffer = new byte[MessageHeader.Length];

buffer = this._Header.ToBytes();

buffer.CopyTo(bytes, 0);

//Time 8

i += MessageHeader.Length;

buffer = new byte[10];

buffer = Encoding.ASCII.GetBytes(this._Time);

buffer.CopyTo(bytes, i);

//Query_Type 1

i += 8;

bytes[i++] = (byte)this._Query_Type;

//Query_Code 10

buffer = new byte[10];

buffer = Encoding.ASCII.GetBytes(this._Query_Code);

buffer.CopyTo(bytes, i);

//Reserve 8

i += 10;

buffer = new byte[8];

buffer = Encoding.ASCII.GetBytes(this._Reserve);

buffer.CopyTo(bytes, i);

return bytes;

}

public override string ToString()

{

return "[/r/n"

+ this._Header.ToString() + "/r/n"

+ string.Format

(

"/tMessageBody:"

+ "/r/n/t/tQuery_Code: {0}"

+ "/r/n/t/tQuery_Type: {1}"

+ "/r/n/t/tReserve: {2}"

+ "/r/n/t/tTime: {3}"

+ "/r/n]"

, this._Query_Code

, this._Query_Type

, this._Reserve

, this._Time

)

+ "/r/n]";

}

}

public class CMPP_QUERY_RESP

{

public MessageHeader Header

{

get

{

return this._Header;

}

}

public string Time

{

get

{

return this._Time;

}

}

public uint Query_Type

{

get

{

return this._Query_Type;

}

}

public string Query_Code

{

get

{

return this._Query_Code;

}

}

public uint Mt_TlMsg

{

get

{

return this._MT_TLMsg;

}

}

public uint Mt_Tlusr

{

get

{

return this._MT_Tlusr;

}

}

public uint Mt_Scs

{

get

{

return this._MT_Scs;

}

}

public uint MT_WT

{

get

{

return this._MT_WT;

}

}

public uint MT_FL

{

get

{

return this._MT_FL;

}

}

public uint MO_Scs

{

get

{

return this._MO_Scs;

}

}

public uint MO_WT

{

get

{

return this._MO_WT;

}

}

public uint MO_FL

{

get

{

return this._MO_FL;

}

}

private MessageHeader _Header;

private string _Time; // 8 Octet String 时间(精确至日)。

private uint _Query_Type; // 1 Unsigned Integer 查询类别:

// 0:总数查询;

// 1:按业务类型查询。

private string _Query_Code; // 10 Octet String 查询码。

private uint _MT_TLMsg; // 4 Unsigned Integer 从SP接收信息总数。

private uint _MT_Tlusr; // 4 Unsigned Integer 从SP接收用户总数。

private uint _MT_Scs; // 4 Unsigned Integer 成功转发数量。

private uint _MT_WT; // 4 Unsigned Integer 待转发数量。

private uint _MT_FL; // 4 Unsigned Integer 转发失败数量。

private uint _MO_Scs; // 4 Unsigned Integer 向SP成功送达数量。

private uint _MO_WT; // 4 Unsigned Integer 向SP待送达数量。

private uint _MO_FL; // 4 Unsigned Integer 向SP送达失败数量。

public const int BodyLength = 8 // Octet String 时间(精确至日)。

+ 1 // Unsigned Integer 查询类别:

// 0:总数查询;

// 1:按业务类型查询。

+ 10 // Octet String 查询码。

+ 4 // Unsigned Integer 从SP接收信息总数。

+ 4 // Unsigned Integer 从SP接收用户总数。

+ 4 // Unsigned Integer 成功转发数量。

+ 4 // Unsigned Integer 待转发数量。

+ 4 // Unsigned Integer 转发失败数量。

+ 4 // Unsigned Integer 向SP成功送达数量。

+ 4 // Unsigned Integer 向SP待送达数量。

+ 4; // Unsigned Integer 向SP送达失败数量。

public CMPP_QUERY_RESP(byte[] bytes)

{

int i = 0;

//header 12

byte[] buffer = new byte[MessageHeader.Length];

Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);

this._Header = new MessageHeader(buffer);

//Time 8

i += MessageHeader.Length;

buffer = new byte[8];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Time = Encoding.ASCII.GetString(buffer);

//Query_Type 1

i += 8;

this._Query_Type = (uint)bytes[i++];

//Query_Code 10

buffer = new byte[10];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Query_Code = Encoding.ASCII.GetString(buffer);

//MT_TLMsg 4

i += 10;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MT_TLMsg = BitConverter.ToUInt32(buffer, 0);

//MT_Tlusr 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MT_Tlusr = BitConverter.ToUInt32(buffer, 0);

//MT_Scs 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MT_Scs = BitConverter.ToUInt32(buffer, 0);

//MT_WT 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MT_WT = BitConverter.ToUInt32(buffer, 0);

//MT_FL 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MT_FL = BitConverter.ToUInt32(buffer, 0);

//MO_Scs 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MO_Scs = BitConverter.ToUInt32(buffer, 0);

//MO_WT 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MO_WT = BitConverter.ToUInt32(buffer, 0);

//MO_FL 4

i += 4;

buffer = new byte[4];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

Array.Reverse(buffer);

this._MO_FL = BitConverter.ToUInt32(buffer, 0);

}

public override string ToString()

{

return "[/r/n"

+ this._Header.ToString() + "/r/n"

+ string.Format

(

"/tMessageBody:"

+ "/r/n/t/tBodyLength: {0}"

+ "/r/n/t/tMO_FL: {1}"

+ "/r/n/t/tMO_Scs: {2}"

+ "/r/n/t/tMO_WT: {3}"

+ "/r/n/t/tMT_FL: {4}"

+ "/r/n/t/tMT_Scs: {5}"

+ "/r/n/t/tMT_TLMsg: {6}"

+ "/r/n/t/tMT_Tlusr: {7}"

+ "/r/n/t/tMT_WT: {8}"

+ "/r/n/t/tQuery_Code: {9}"

+ "/r/n/t/tQuery_Type: {10}"

+ "/r/n/t/tTime: {11}"

, CMPP_QUERY_RESP.BodyLength

, this._MO_FL

, this._MO_Scs

, this._MO_WT

, this._MT_FL

, this._MT_Scs

, this._MT_TLMsg

, this._MT_Tlusr

, this._MT_WT

, this._Query_Code

, this._Query_Type

, this._Time

)

+ "/r/n]";

}

}

public class CMPP_ACTIVE_TEST

{

private MessageHeader _Header;

public MessageHeader Header

{

get

{

return this._Header;

}

}

public CMPP_ACTIVE_TEST(uint Sequence_Id)

{

this._Header = new MessageHeader(MessageHeader.Length, CMPP_Command_Id.CMPP_ACTIVE_TEST, Sequence_Id);

}

public byte[] ToBytes()

{

return this._Header.ToBytes();

}

public override string ToString()

{

return this._Header.ToString();

}

}

public class CMPP_ACTIVE_TEST_RESP

{

private MessageHeader _Header;

private uint _Reserved;

public uint Reserved

{

get

{

return this._Reserved;

}

}

public MessageHeader Header

{

get

{

return this._Header;

}

}

public const int Bodylength = 1;

public CMPP_ACTIVE_TEST_RESP(uint Sequence_Id)

{

this._Header = new MessageHeader(MessageHeader.Length + Bodylength, CMPP_Command_Id.CMPP_ACTIVE_TEST_RESP, Sequence_Id);

// this._Header = new MessageHeader((uint)(MessageHeader.Length + BodyLength), CMPP_Command_Id.CMPP_ACTIVE_TEST_RESP, Sequence_Id);

this._Reserved = 0;

}

public CMPP_ACTIVE_TEST_RESP(byte[] bytes)

{

int i = 0;

//header

byte[] buffer = new byte[MessageHeader.Length];

Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);

this._Header = new MessageHeader(buffer);

//Reserved 1

i += MessageHeader.Length;

this._Reserved = bytes[i];

}

public byte[] ToBytes()

{

int i = 0;

byte[] bytes = new byte[MessageHeader.Length + Bodylength];

byte[] buffer = new byte[MessageHeader.Length];

buffer = this._Header.ToBytes();

Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);

i += MessageHeader.Length;

//Reserved

bytes[i++] = (byte)this.Reserved;

return bytes;

}

public override string ToString()

{

return this._Header.ToString();

}

}

}

//------------------------------------------------------------------------------

文件名MessageEventArgs.cs

//------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Text;

namespace AsiaINFO.SMS.CMPP2

{

/// <summary>

/// 消息包

/// </summary>

public class MessageEventArgs : EventArgs

{

private byte[] _HeaderData;

private MessageHeader _Header;

private byte[] _BodyData;

public byte[] BodyData

{

get

{

return this._BodyData;

}

}

public MessageHeader Header

{

get

{

return this._Header;

}

}

public byte[] HeaderData

{

get

{

return this._HeaderData;

}

}

public MessageEventArgs(byte[] bytes)

{

this._HeaderData = new byte[MessageHeader.Length];

Buffer.BlockCopy(bytes, 0, this._HeaderData, 0, MessageHeader.Length);

this._Header = new MessageHeader(this._HeaderData);

this._BodyData = new byte[this._Header.Total_Length - MessageHeader.Length];

Buffer.BlockCopy(bytes, MessageHeader.Length, this._BodyData, 0, this._BodyData.Length);

}

}

}

//------------------------------------------------------------------------------

文件名StateDictionary.cs

//------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace AsiaINFO.SMS.CMPP2

{

/// <summary>

/// 状态字典

/// </summary>

public class StateDictionary

{

/// <summary>

/// 连接状态字典

/// </summary>

/// <param name="state"></param>

/// <returns></returns>

public static string ConnResDictionary(uint state)

{

string result = "连接结果:";

switch (state)

{

case 0: result += "成功!"; break;

case 1: result += "错误! 原因:消息结构错"; break;

case 2: result += "错误! 原因:非法源地址"; break;

case 3: result += "错误! 原因:认证错误"; break;

case 4: result += "错误! 原因:版本太高"; break;

case 997: result += "错误! 原因:连接超时"; break;

case 998: result += "错误! 原因:远程服务器主动断开"; break;

case 999: result += "错误! 原因:未知错误"; break;

default: result = "错误! 原因:其他错误" + state.ToString(); break;

}

return result;

}

}

}

//------------------------------------------------------------------------------

文件名SyncEvents.cs

//------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

namespace AsiaINFO.SMS.CMPP2

{

/// <summary>

/// 同步信号量

/// </summary>

public class SyncEvents

{

public SyncEvents()

{

_newItemEvent = new AutoResetEvent(false);

_exitThreadEvent = new ManualResetEvent(false);

_eventArray = new WaitHandle[2];

_eventArray[0] = _newItemEvent;

_eventArray[1] = _exitThreadEvent;

}

/// <summary>

/// 退出信号

/// </summary>

public EventWaitHandle ExitThreadEvent

{

get { return _exitThreadEvent; }

}

/// <summary>

/// 收到数据信号

/// </summary>

public EventWaitHandle NewItemEvent

{

get { return _newItemEvent; }

}

public WaitHandle[] EventArray

{

get { return _eventArray; }

}

private EventWaitHandle _newItemEvent;

private EventWaitHandle _exitThreadEvent;

private WaitHandle[] _eventArray;

}

}

//------------------------------------------------------------------------------

文件名Util.cs

//------------------------------------------------------------------------------

using System;

using System.Net.Sockets;

namespace AsiaINFO.SMS.CMPP2

{

public class Util

{

//private static object _SyncLockObject = new object();

public static string Get_MMDDHHMMSS_String(DateTime dt)

{

string s = dt.Month.ToString().PadLeft(2, '0');

s += dt.Day.ToString().PadLeft(2, '0');

s += dt.Hour.ToString().PadLeft(2, '0');

s += dt.Minute.ToString().PadLeft(2, '0');

s += dt.Second.ToString().PadLeft(2, '0');

return s;

}

public static string Get_YYYYMMDD_String(DateTime dt)

{

string s = dt.Year.ToString().PadLeft(4, '0');

s += dt.Month.ToString().PadLeft(2, '0');

s += dt.Day.ToString().PadLeft(2, '0');

return s;

}

internal static void WriteToStream(byte[] bytes, NetworkStream Stream)

{

if (Stream.CanWrite)

{

//lock (_SyncLockObject)

//{

Stream.Write(bytes, 0, bytes.Length);

//}

}

}

internal static byte[] ReadFromStream(int Length, NetworkStream Stream)

{

byte[] bytes = null;

if (Stream.CanRead)

{

if (Stream.DataAvailable)

{

bytes = new byte[Length];

int r = 0;

int l = 0;

//lock (_SyncLockObject)

{

while (l < Length)

{

r = Stream.Read(bytes, l, Length - l);

l += r;

}

}

}

}

return bytes;

}

}

}

//------------------------------------------------------------------------------

文件名WapPush.cs

//------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace AsiaINFO.SMS.CMPP2

{

public class WapPush

{

private static WapPush push = null;

public static WapPush GetInstance()

{

if (null == push)

{

push = new WapPush();

}

return push;

}

//第一部分

static private readonly byte[] WapPushHeader1 = new byte[]

{

0x0B, 0x05, 0x04, 0x0B, 0x84, 0x23, 0xF0, 0x00, 0x03, 0x03, 0x01, 0x01

};

//第二部分

static private readonly byte[] WapPushHeader2 = new byte[]

{

0x29, 0x06, 0x06, 0x03, 0xAE, 0x81, 0xEA, 0x8D, 0xCA

};

//第三部分

static private readonly byte[] WapPushIndicator = new byte[]

{

0x02, 0x05, 0x6A, 0x00, 0x45, 0xC6, 0x0C, 0x03

};

//第四部分:URL去掉http://后的UTF8编码

//第五部分

static private readonly byte[] WapPushDisplayTextHeader = new byte[]

{

0x00, 0x01, 0x03,

};

//第六部分:消息文字的UTF8编码

//第七部分:

static private readonly byte[] EndOfWapPush = new byte[]

{

0x00, 0x01, 0x01,

};

public byte[] toBytes(string WAP_Msg, string WAP_URL)

{

byte[] submitData = new byte[400];

int index = 0;

WapPushHeader1.CopyTo(submitData, index);

index += WapPushHeader1.Length;

WapPushHeader2.CopyTo(submitData, index);

index += WapPushHeader2.Length;

WapPushIndicator.CopyTo(submitData, index);

index += WapPushIndicator.Length;

byte[] url = Encoding.UTF8.GetBytes(WAP_URL);

url.CopyTo(submitData, index);

index += url.Length;

WapPushDisplayTextHeader.CopyTo(submitData, index);

index += WapPushDisplayTextHeader.Length;

byte[] msg2 = Encoding.UTF8.GetBytes(WAP_Msg);

msg2.CopyTo(submitData, index);

index += msg2.Length;

EndOfWapPush.CopyTo(submitData, index);

index += 3;

byte[] reVal = new byte[index];

for (int i = 0; i < reVal.Length; i++)

{

reVal = submitData;

}

return (reVal);

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐