下载参考程序 :http://download.youkuaiyun.com/detail/adama119/4189313
短信行业已经很成熟了,到处可以找到资料。本人在这个行业干过几年,做过3套短信平台都在省级单位省用,做的最复杂的自然是SP的应用,曾经在广电集团工作时做的内容确实非常复杂自己都觉得头疼,当然也和水平有限有关。
2010年底给江苏某国企做了一套行业应用的短信系统,做短信平台大量工作还是围绕业务开发WEB方面内容。这次网关客户端的是用C#开发的,目标为50条/秒,性能上应该没什么问题,支持普通短信但是长短信对方没要就没写,需要的朋友可以自行修改开发。以下贴出SMGP3.0源代码给各位需要的朋友做个参考,运行到现在没有发现任何问题。这里只贴出SMGP接口,至于程序就自己做吧,如果需要也可以联系我
邮箱 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.SMGP3
{
/// <summary>
/// @Description:SMGP3 短消息电信网关客户端
/// @Author:Adama SUN
/// @Mail:spf193@gmail.com
/// @Copyright (C) 2010 AsiaINFO. All rights reserved.
/// </summary>
public class SMGPClient
{
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">SMGP接口 接收数据队列</param>
/// <param name="syncEvents">SMGP接口信号:检查是否需要退出线程,SMGP接口新数据到达(通知)</param>
public SMGPClient(Queue<byte[]> queue, SyncEvents syncEvents)
{
if (queue == null || syncEvents == null)
throw new Exception("参数不能为空!");
_receiveQueue = queue;
_syncEvents = syncEvents;
}
#region private field
private Queue<byte[]> _receiveQueue;//接收队列
private SyncEvents _syncEvents;//信号
// private string _Host; //主机
// private int _Port; //端口
// private string _ClientID; //账号
// 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)
{
Login login = new Login(UserID, Password, 2, DateTime.Now,0x30, 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(login.ToBytes(), this._NetworkStream);
this.StartRun();
}
/// <summary>
/// 中断
/// </summary>
/// <param name="SequenceId"></param>
public void Terminate(uint SequenceId)
{
MessageHeader terminate = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Exit, SequenceId);
// OnMsg(terminate.ToString());
this.WriteToStreamWithLock(terminate.ToBytes(), this._NetworkStream);
}
/// <summary>
/// ACTIVE_TEST
/// </summary>
/// <param name="SequenceId"></param>
public void ActiveTest(uint SequenceId)
{
MessageHeader activeTest = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Active_Test, SequenceId);
this.WriteToStreamWithLock(activeTest.ToBytes(), this._NetworkStream);
}
/// <summary>
/// ACTIVE_TEST_RESP
/// </summary>
/// <param name="SequenceId"></param>
public void ActiveResp(uint SequenceId)
{
Active_Test_Resp response = new Active_Test_Resp(SequenceId);
this.WriteToStreamWithLock(response.ToBytes(), this._NetworkStream);
}
/// <summary>
/// 发送DELIVER_RESP
/// </summary>
/// <param name="Msg_Id"></param>
/// <param name="Result"></param>
public void DeliverResp(ulong Msg_Id, uint Result, uint SequenceId)
{
Deliver_Resp deliverResp = new 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, uint SequenceId)
{
Query query = new Query(Time, QueryType, QueryCode, SequenceId);
this.WriteToStreamWithLock(query.ToBytes(), this._NetworkStream);
}
/// <summary>
/// 发送短信
/// </summary>
/// <param name="ServiceID">业务代码</param>
/// <param name="FeeType">资费类别</param>
/// <param name="FeeCode">资费代码(以分为单位)</param>
/// <param name="FixedFee">短消息的包月费/封顶费(以分为单位)</param>
/// <param name="SrcTermID">短消息发送方号码</param>>
/// <param name="DestTermID">接收短信的号码_1个号码</param>
/// <param name="MsgContent">短信内容</param>
/// <param name="ProductID">产品ID</param>
/// <param name="LinkID"></param>
public void Submit(string ServiceID, string FeeType, string FeeCode, string FixedFee, string SrcTermID
, string mobile, string MsgContent, string ProductID, string LinkID, uint SequenceId)
{
Submit(ServiceID, FeeType, FeeCode, FixedFee, SrcTermID, mobile, new string[] { mobile }, MsgContent, ProductID, LinkID, SequenceId);
}
/// <summary>
/// 发送短信
/// </summary>
/// <param name="ServiceID">业务代码</param>
/// <param name="FeeType">资费类别</param>
/// <param name="FeeCode">资费代码(以分为单位)</param>
/// <param name="FixedFee">短消息的包月费/封顶费(以分为单位)</param>
/// <param name="SrcTermID">短消息发送方号码</param>
/// <param name="ChargeTermID">被计费用户的号码</param>
/// <param name="DestTermID">接收短信的号码_多个号码</param>
/// <param name="MsgContent">短信内容</param>
/// <param name="ProductID">产品ID</param>
/// <param name="LinkID"></param>
public void Submit(string ServiceID, string FeeType, string FeeCode, string FixedFee, string SrcTermID, string ChargeTermID
, string[] DestTermID, string MsgContent, string ProductID, string LinkID, uint SequenceId)
{
Submit(1, ServiceID, FeeType, FeeCode, FixedFee, SrcTermID, ChargeTermID, DestTermID, MsgContent, "", ProductID, LinkID, SequenceId);
}
/// <summary>
/// 发送短信
/// </summary>
/// <param name="NeedReport">是否要返回状态确认报告</param>
/// <param name="ServiceID">业务代码</param>
/// <param name="FeeType">资费类别</param>
/// <param name="FeeCode">资费代码(以分为单位)</param>
/// <param name="FixedFee">短消息的包月费/封顶费(以分为单位)</param>
/// <param name="SrcTermID">短消息发送方号码</param>
/// <param name="ChargeTermID">被计费用户的号码</param>
/// <param name="DestTermID">接收短信的号码_多个号码</param>
/// <param name="MsgContent">短信内容</param>
/// <param name="Reserve">保留</param>
/// <param name="ProductID">产品ID</param>
/// <param name="LinkID"></param>
public void Submit(uint NeedReport, string ServiceID, string FeeType, string FeeCode,string FixedFee,string SrcTermID,string ChargeTermID
, string[] DestTermID, string MsgContent, string Reserve, string ProductID, string LinkID, uint SequenceId)
{
//这里的字段根据需要设定
Submit submit = new Submit(SequenceId);
submit.MsgType = 6; // uint 6=MT 消息(SP 发给终端,包括WEB 上发送的点对点短消息);
submit.NeedReport = NeedReport; // uint 0=不要求返回状态报告; 1=要求返回状态报告;
submit.Priority = 1;
submit.ServiceID = ServiceID;
submit.FeeType=FeeType;
submit.FeeCode=FeeCode;
submit.FixedFee=FixedFee;
submit.MsgFormat=15;
submit.ValidTime = ""; //Util.Get_MMDDHHMMSS_String(DateTime.Now.AddHours(5)) + "032+"; // 存活有效期,格式遵循SMPP3.3协议。
submit.AtTime=""; //Util.Get_MMDDHHMMSS_String(DateTime.Now) + "032+"; // 短消息定时发送时间,格式遵循SMPP3.3 以上版本协议。
//submit.SrcTermID="118"+SrcTermID;
submit.SrcTermID = SrcTermID;
submit.ChargeTermID = ChargeTermID;
submit.DestTermID=DestTermID;
submit.DestTermIDCount=(uint)submit.DestTermID.Length;
submit.MsgContent=MsgContent;
submit.Reserve=Reserve;
submit.ProductID=ProductID;
submit.LinkID=LinkID;
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("SMGPClient启动错误:" + 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>
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)
{
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.PacketLength];
Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);
int l = (int)header.PacketLength - 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("SMGPClient接收错误:" + ex.Message);
}
OnThreadState(ThreadState.Stopped);
}
#endregion
}
}
//------------------------------------------------------------------------------
//文件MessageEventArgs.cs
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace AsiaINFO.SMS.SMGP3
{
/// <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.PacketLength - MessageHeader.Length];
Buffer.BlockCopy(bytes, MessageHeader.Length, this._BodyData, 0, this._BodyData.Length);
}
}
}
//------------------------------------------------------------------------------
//文件SMGPMessages.cs
//------------------------------------------------------------------------------
using System;
using System.Text;
using System.Security.Cryptography;
using System.Collections;
namespace AsiaINFO.SMS.SMGP3
{
/// <summary>
/// SMGP3 消息定义 (RequestId)
/// </summary>
public enum SMGP3_RequestId : uint
{
Login = 0x00000001 //客户端登录 ----sp use
,
Login_Resp = 0x80000001 //客户端登录应答 ----sp use
,
Submit = 0x00000002 //提交短消息 ----sp use
,
Submit_Resp = 0x80000002 //提交短消息应答 ----sp use
,
Deliver = 0x00000003 //下发短消息 ----sp use
,
Deliver_Resp = 0x80000003 //下发短消息应答 ----sp use
,
Active_Test = 0x00000004 //链路检测 ----sp use
,
Active_Test_Resp = 0x80000004 //链路检测应答 ----sp use
,
Forward = 0x00000005 //短消息前转
,
Forward_Resp = 0x80000005 //短消息前转应答
,
Exit = 0x00000006 //退出请求 ----sp use
,
ExitResp = 0x80000006 //退出应答 ----sp use
,
Query = 0x00000007 //SP 统计查询
,
Query_Resp = 0x80000007 //SP 统计查询应答
,
Query_TE_Route = 0x00000008 //查询TE 路由
,
Query_TE_Route_Resp = 0x80000008 //查询TE 路由应答
,
Query_SP_Route = 0x00000009 //查询SP 路由
,
Query_SP_Route_Resp = 0x80000009 //查询SP 路由应答
,
Payment_Request = 0x0000000A //扣款请求(用于预付费系统,参见增值业务计费方案)
,
Payment_Request_Resp = 0x8000000A //扣款请求响应(用于预付费系统,参见增值业务计费方案,下同)
,
Payment_Affirm = 0x0000000B //扣款确认(用于预付费系统,参见增值业务计费方案)
,
Payment_Affirm_Resp = 0x8000000B //扣款确认响应(用于预付费系统,参见增值业务计费方案)
,
Query_UserState = 0x0000000C //查询用户状态(用于预付费系统,参见增值业务计费方案)
,
Query_UserState_Resp = 0x8000000C //查询用户状态响应(用于预付费系统,参见增值业务计费方案)
,
Get_All_TE_Route = 0x0000000D //获取所有终端路由
,
Get_All_TE_Route_Resp = 0x8000000D //获取所有终端路由应答
,
Get_All_SP_Route = 0x0000000E //获取所有SP 路由
,
Get_All_SP_Route_Resp = 0x8000000E //获取所有SP 路由应答
,
Update_TE_Route = 0x0000000F //SMGW 向GNS 更新终端路由
,
Update_TE_Route_Resp = 0x8000000F //SMGW 向GNS 更新终端路由应答
,
Update_SP_Route = 0x00000010 //SMGW 向GNS 更新SP 路由
,
Update_SP_Route_Resp = 0x80000010 // SMGW 向GNS 更新SP 路由应答
,
Push_Update_TE_Route = 0x00000011 //GNS 向SMGW 更新终端路由
,
Push_Update_TE_Route_Resp = 0x80000011 //GNS 向SMGW 更新终端路由应答
,
Push_Update_SP_Route = 0x00000012 //GNS 向SMGW 更新SP 路由
,
Push_Update_SP_Route_Resp = 0x80000012 // GNS 向SMGW 更新SP 路由应答
}
/// <summary>
/// 消息头
/// </summary>
public class MessageHeader
{
public const int Length = 4 + 4 + 4;
public SMGP3_RequestId RequestId
{
get
{
return this._RequestId;
}
}
public uint SequenceID
{
get
{
return this._SequenceID;
}
}
public uint PacketLength
{
get
{
return this._PacketLength;
}
}
private uint _PacketLength; // 4 Unsigned Integer 数据包长度
private SMGP3_RequestId _RequestId; // 4 Unsigned Integer 命令或响应类型
private uint _SequenceID; // 4 Unsigned Integer 消息流水号
public MessageHeader
(
uint PacketLength
, SMGP3_RequestId RequestId
, uint SequenceID
) //发送前
{
this._PacketLength = PacketLength;
this._RequestId = RequestId;
this._SequenceID = SequenceID;
}
public MessageHeader(byte[] bytes)
{
byte[] buffer = new byte[4];
Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
Array.Reverse(buffer);
this._PacketLength = BitConverter.ToUInt32(buffer, 0);
Buffer.BlockCopy(bytes, 4, buffer, 0, buffer.Length);
Array.Reverse(buffer);
this._RequestId = (SMGP3_RequestId)BitConverter.ToUInt32(buffer, 0);
Buffer.BlockCopy(bytes, 8, buffer, 0, buffer.Length);
Array.Reverse(buffer);
this._SequenceID = BitConverter.ToUInt32(buffer, 0);
}
public byte[] ToBytes()
{
byte[] bytes = new byte[MessageHeader.Length];
byte[] buffer = BitConverter.GetBytes(this._PacketLength);
Array.Reverse(buffer);
Buffer.BlockCopy(buffer, 0, bytes, 0, 4);
buffer = BitConverter.GetBytes((uint)this._RequestId);
Array.Reverse(buffer);
Buffer.BlockCopy(buffer, 0, bytes, 4, 4);
buffer = BitConverter.GetBytes(this._SequenceID);
Array.Reverse(buffer);
Buffer.BlockCopy(buffer, 0, bytes, 8, 4);
return bytes;
}
public override string ToString()
{
return string.Format("MessageHeader: RequestId={0} Sequence_Id={1} Total_Length={2}"
, this._RequestId
, this._SequenceID
, this._PacketLength
);
}
}
public class Login
{
public const int BodyLength = 8 + 16 + 1 + 4+1;
private string _ClientID; // 8 Octet String 客户端用来登录服务器端的用户账号。
private string _Password;
private byte[] _AuthenticatorSource; // 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:
private uint _LoginMode; // 1 Unsigned Integer 客户端用来登录服务器端的登录类型。
// AuthenticatorSource =
// MD5(Source_Addr+9 字节的0 +shared secret+timestamp)
// Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。
private uint _ClientVersion; // 1 Unsigned Integer 客户端支持的协议版本号
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;
}
}
/// <summary>
///
/// </summary>
/// <param name="ClientID">客户端用来登录服务器端的用户账号</param>
/// <param name="Password">登录密码</param>
/// <param name="LoginMode">客户端用来登录服务器端的登录类型。0=发送短消息(send mode);1=接收短消息(receive mode);2=收发短消息(transmit mode);</param>
/// <param name="Timestamp">时间戳</param>
/// <param name="Version">客户端支持的协议版本号。</param>
/// <param name="Sequence_Id"></param>
public Login
(
string ClientID
, string Password
, uint LoginMode
, DateTime Timestamp
, uint ClientVersion
, uint Sequence_Id
)
{
this._Header = new MessageHeader(MessageHeader.Length + BodyLength, SMGP3_RequestId.Login, Sequence_Id);
this._ClientID = ClientID;
this._Password = Password;
this._LoginMode = LoginMode;
string s = Util.Get_MMDDHHMMSS_String(Timestamp);
this._Timestamp = UInt32.Parse(s);
//byte[] buffer = new byte[8 + 7 + this._Password.Length + 10];
//Encoding.ASCII.GetBytes(this._ClientID).CopyTo(buffer, 0);
//Encoding.ASCII.GetBytes(this._Password).CopyTo(buffer, 8 + 7);
//Encoding.ASCII.GetBytes(s).CopyTo(buffer, 8 + 7 + this._Password.Length);
//this._AuthenticatorSource = new MD5CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length);
byte[] clientid = System.Text.Encoding.ASCII.GetBytes(ClientID);
byte[] password = System.Text.Encoding.ASCII.GetBytes(Password);
byte[] timestamp = System.Text.Encoding.ASCII.GetBytes(s);
byte[] data = new byte[clientid.Length + 7 + password.Length + timestamp.Length];
Array.Copy(clientid, data, clientid.Length);
Array.Copy(password, 0, data, clientid.Length + 7, password.Length);
Array.Copy(timestamp, 0, data, clientid.Length + 7 + password.Length, timestamp.Length);
System.Security.Cryptography.MD5 MD5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
_AuthenticatorSource = MD5.ComputeHash(data);
this._ClientVersion = ClientVersion;
}
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);
//ClientID 8
i += MessageHeader.Length;
buffer = Encoding.ASCII.GetBytes(this._ClientID);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
//AuthenticatorSource 16
i += 8;
buffer = this._AuthenticatorSource;
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //16
//LoginMode 1
i += 16;
bytes[i++] = (byte)this._LoginMode; //登录类型
//Timestamp
buffer = BitConverter.GetBytes(this._Timestamp);
Array.Reverse(buffer);
buffer.CopyTo(bytes, i);
//version 1
i += 4;
bytes[i] = (byte)this._ClientVersion; //客户端版本
return (bytes);
}
public override string ToString()
{
return string.Format("Header={0} AuthenticatorSource={1} Password={2} ClientID={3} LoginMode={4} Timestamp={5} ClientVersion={6}"
, this._Header.ToString()
,this._AuthenticatorSource
, this._Password
, this._ClientID
, this._LoginMode
,this._Timestamp
, this._ClientVersion);
}
}
public class Login_Resp
{
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 _ServerVersion; // 1 Unsigned Integer 服务器端支持的最高版本号
public byte[] AuthenticatorISMG
{
get
{
return this._AuthenticatorISMG;
}
}
/// <summary>
/// 请求返回结果
/// </summary>
public uint Status
{
get
{
return this._Status;
}
}
/// <summary>
/// 服务器版本号
/// </summary>
public uint ServerVersion
{
get
{
return this._ServerVersion;
}
}
public MessageHeader Header
{
get
{
return this._Header;
}
}
public Login_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;
buffer = new byte[4];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
Array.Reverse(buffer);
this._Status = BitConverter.ToUInt32(buffer, 0);
//AuthenticatorISMG 16
i += 4;
this._AuthenticatorISMG = new byte[16];
Buffer.BlockCopy(bytes, MessageHeader.Length + 4, this._AuthenticatorISMG, 0, this._AuthenticatorISMG.Length);
//version 1
i += 16;
this._ServerVersion = bytes[i];
}
public override string ToString()
{
return string.Format("Header={0} AuthenticatorISMG={1} BodyLength={2} Status={3} ServerVersion={4}"
, this._Header.ToString()
, this._AuthenticatorISMG
, Login_Resp.BodyLength
, this._Status
, this._ServerVersion);
}
}
public class Submit
{
private int _BodyLength;
public const int FixedBodyLength = 1
+ 1
+ 1
+ 10
+ 2
+ 6
+ 6
+ 1
+ 17
+ 17
+ 21
+ 21
+ 1
//+ 21*DestTermIDCount (_DestTermID字段)
+ 1
//+ MsgLength (Msg_Content字段)
+ 8;
// tlv
private uint _MsgType; // 1 Unsigned Integer 短消息类型。
private uint _NeedReport; // 1 Unsigned Integer 是否要求返回状态报。
private uint _Priority; // 1 Unsigned Integer 短消息发送优先级。
private string _ServiceID; // 10 Octet String 业务代码
private string _FeeType; // 2 Octet String 收费类型。
private string _FeeCode; // 6 Octet String 资费代码。
private string _FixedFee; // 6 Octet String 包月费/封顶费
private uint _MsgFormat; // 1 Unsigned Integer 短消息格式
private string _ValidTime; // 17 Octet String 短消息有效时间。
private string _AtTime; // 17 Octet String 短消息定时发送时间,格式遵循SMPP3.3协议。
private string _SrcTermID; // 21 Octet String 短信息发送方号码
private string _ChargeTermID; // 21 Octet String 计费用户号码
private uint _DestTermIDCount; // 1 Unsigned Integer 短消息接收号码总数。
private string[] _DestTermID; // 21*DestTermIDCount Octet String 短消息接收号码。
private uint _MsgLength; // 1 Unsigned Integer 短消息长度
private string _MsgContent; // MsgLength Octet String 短消息内容。
private string _Reserve; // 8 Octet String 保留
// tlv
private string _ProductID = "";
private string _LinkID = "";
private Tlv[] _OtherTlvArray = null;
public MessageHeader Header
{
get
{
return _Header;
}
set
{
_Header = value;
}
}
private MessageHeader _Header;
private uint _Sequence_Id;
public Submit(uint Sequence_Id)
{
this._Sequence_Id = Sequence_Id;
}
private byte[] _MsgContent_Bytes;
private void SetHeader()
{
//byte[] buf;
switch (this._MsgFormat)
{
case 8:
_MsgContent_Bytes = Encoding.BigEndianUnicode.GetBytes(this._MsgContent);
break;
case 15: //gb2312
_MsgContent_Bytes = Encoding.GetEncoding("gb2312").GetBytes(this._MsgContent);
break;
case 0: //ascii
case 3: //短信写卡操作
case 4: //二进制信息
default:
_MsgContent_Bytes = Encoding.ASCII.GetBytes(this._MsgContent);
break;
}
this._MsgLength = (uint)_MsgContent_Bytes.Length;
this._BodyLength = (int)(FixedBodyLength + 21 * this._DestTermID.Length + this._MsgLength);
if (_OtherTlvArray != null)
{
for (int i = 0; i < _OtherTlvArray.Length; i++)
{
if(_OtherTlvArray[i].Length>0)
_BodyLength += _OtherTlvArray[i].Length + 4;
}
}
this._Header = new MessageHeader((uint)(MessageHeader.Length + this._BodyLength), SMGP3_RequestId.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;
bytes[i++] = (byte)this._MsgType; //[12,12]
bytes[i++] = (byte)this._NeedReport; //[13,13]
bytes[i++] = (byte)this._Priority; //[14,14]
//ServiceId
buffer = Encoding.ASCII.GetBytes(this._ServiceID);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //10 //[15,24]
//FeeType
i += 10;
buffer = Encoding.ASCII.GetBytes(this._FeeType);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //2 //[25,26]
//FeeCode
i += 2;
buffer = Encoding.ASCII.GetBytes(this._FeeCode);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6 //[27,32]
//FixedFee
i += 6;
buffer = Encoding.ASCII.GetBytes(this._FixedFee);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //6 //[33,38]
//MsgFormat
i += 6;
bytes[i++] = (byte)this._MsgFormat; //1 //[39,39]
//ValId_Time
buffer = Encoding.ASCII.GetBytes(this._ValidTime);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17 //[40,56]
//AtTime
i += 17;
buffer = Encoding.ASCII.GetBytes(this._AtTime);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //17 //[57,73]
//SrcTermID
i += 17;
buffer = Encoding.ASCII.GetBytes(this._SrcTermID);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21 //[74,94]
//ChargeTermID
i += 21;
buffer = Encoding.ASCII.GetBytes(this._ChargeTermID);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //21 //[95,115]
//DestTermIDCount
i += 21;
this._DestTermIDCount = (uint)this._DestTermID.Length;
bytes[i++] = (byte)this._DestTermIDCount; //1 //[116,116]
//DestTermID
foreach (string s in this._DestTermID)
{
buffer = Encoding.ASCII.GetBytes(s);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
i += 21;
}
//MsgLength
bytes[i++] = (byte)this._MsgLength;
//MsgContent
//buffer = Encoding.
Buffer.BlockCopy(this._MsgContent_Bytes, 0, bytes, i, this._MsgContent_Bytes.Length);
//Reserve
i += (int)this._MsgLength;
buffer = Encoding.ASCII.GetBytes(this._Reserve);
Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length); //8
//tlv
i += 8;
if (_OtherTlvArray != null)
{
for (int j = 0; j < _OtherTlvArray.Length; j++)
{
if (_OtherTlvArray[j].Length > 0)
{
Buffer.BlockCopy(_OtherTlvArray[j].TlvBuf, 0, bytes, i, _OtherTlvArray[j].Length); //8
i += _OtherTlvArray[j].Length;
}
}
}
return bytes;
}
public void AddTlv(short tag, string value)
{
if (this._OtherTlvArray == null)
{
Tlv[] tmp = new Tlv[1];
tmp[0] = new Tlv(tag, value);
this._OtherTlvArray = tmp;
}
else
{
int find = 0;
for (int i = 0; i < _OtherTlvArray.Length; i++)
{
if (_OtherTlvArray[i].Tag == tag)
{
find = 1;
_OtherTlvArray[i] = new Tlv(tag, value);
}
}
if (find == 0)
{
Tlv[] tmp = new Tlv[_OtherTlvArray.Length + 1];
Array.Copy(_OtherTlvArray, tmp, _OtherTlvArray.Length);
//Buffer.BlockCopy(_OtherTlvArray, 0, tmp, 0, _OtherTlvArray.Length);
tmp[_OtherTlvArray.Length] = new Tlv(tag, value);
this._OtherTlvArray = tmp;
}
}
this.SetHeader();
//if (tag == TlvId.LinkID)
//{
// this._LinkID = value;
//}
//else if (tag == TlvId.Mserviceid)
//{
// this._ProductID = value;
//}
//else
//{
// if (this.OtherTlvArray == null)
// {
// Tlv[] tmp = new Tlv[1];
// tmp[0] = new Tlv(tag, value);
// this.OtherTlvArray = tmp;
// }
// else
// {
// int find = 0;
// for (int i = 0; i < OtherTlvArray.Length; i++)
// {
// if (OtherTlvArray[i].Tag == tag)
// {
// find = 1;
// OtherTlvArray[i] = new Tlv(tag, value);
// }
// }
// if (find == 0)
// {
// Tlv[] tmp = new Tlv[OtherTlvArray.Length + 1];
// Buffer.BlockCopy(OtherTlvArray, 0, tmp, 0, OtherTlvArray.Length);
// tmp[OtherTlvArray.Length] = new Tlv(tag, value);
// this.OtherTlvArray = tmp;
// }
// }
//}
}
/// <summary>
/// 短消息类型
///
/// 对于回执消息该字段无效;对于文本短消息,该字段表示短消息的消息流向:
/// 0=MO 消息(终端发给SP);
/// 6=MT 消息(SP 发给终端,包括WEB 上发送的点对点短消息);
/// 7=点对点短消息;
/// </summary>
public uint MsgType
{
get
{
return this._MsgType;
}
set
{
this._MsgType = value;
}
}
/// <summary>
/// 是否要求返回状态报告
/// 0=不要求返回状态报告;
/// 1=要求返回状态报告;
/// </summary>
public uint NeedReport
{
get
{
return this._NeedReport;
}
set
{
this._NeedReport = value;
}
}
/// <summary>
/// 短消息发送优先级。
/// 0=低优先级;
/// 1=普通优先级;
/// 2=较高优先级;
/// 3=高优先级;
/// </summary>
public uint Priority
{
get
{
return this._Priority;
}
set
{
this._Priority = value;
}
}
/// <summary>
/// 业务代码
/// </summary>
public string ServiceID
{
get
{
return this._ServiceID;
}
set
{
this._ServiceID = value;
}
}
/// <summary>
/// 对计费用户采取的收费类型。
///
/// 00=免费,此时FixedFee 和FeeCode 无效;
/// 01=按条计信息费,此时FeeCode 表示每条费用,FixedFee 无效;
/// 02=按包月收取信息费,此时FeeCode 无效,FixedFee 表示包月费用;
/// 03=按封顶收取信息费,若按条收费的费用总和达到或超过封顶费后,则按照封顶费用收取信息费;
/// 若按条收费的费用总和没有达到封顶费用,则按照每条费用总和收取信息费。FeeCode表示每条费用,FixedFee 表示封顶费用。
/// </summary>
public string FeeType
{
get
{
return this._FeeType;
}
set
{
this._FeeType = value;
}
}
/// <summary>
/// 每条短消息费率
///
/// 单位为“分”。
/// </summary>
public string FeeCode
{
get
{
return this._FeeCode;
}
set
{
this._FeeCode = value;
}
}
/// <summary>
/// 短消息的包月费/封顶费
///
/// 单位为“分”
/// </summary>
public string FixedFee
{
get
{
return this._FixedFee;
}
set
{
this._FixedFee = value;
}
}
/// <summary>
/// 短消息内容体的编码格式。
///
/// 0=ASCII 编码;
/// 3=短消息写卡操作;
/// 4=二进制短消息;
/// 8=UCS2 编码;
/// 15=GB18030 编码;
/// 246(F6)=(U)SIM 相关消息;
/// 对于文字短消息,要求MsgFormat=15。对于回执消息,要求MsgFormat=0。
/// </summary>
public uint MsgFormat
{
get
{
return this._MsgFormat;
}
set
{
this._MsgFormat = value;
if (this._MsgContent != null)
{
this.SetHeader();
}
}
}
/// <summary>
/// 短消息有效时间
///
/// 格式遵循SMPP3.3 以上版本协议
/// 短消息有效时间在转发过程中保持不变
/// </summary>
public string ValidTime
{
get
{
return this._ValidTime;
}
set
{
this._ValidTime = value;
}
}
/// <summary>
/// 短消息定时发送时间
///
/// 格式遵循SMPP3.3 以上版本协议
/// 短消息定时发送时间在转发过程中保持不变
/// </summary>
public string AtTime
{
get
{
return this._AtTime;
}
set
{
this._AtTime = value;
}
}
/// <summary>
/// 短消息发送方号码。
///
/// 对于MT 消息,SrcTermID 格式为“118+SP 服务代码+其它(可选)”
/// 例如SP 服务代码为1234 时,SrcTermID 可以为1181234 或118123456 等。
/// </summary>
public string SrcTermID
{
get
{
return this._SrcTermID;
}
set
{
this._SrcTermID = value;
}
}
/// <summary>
/// 计费用户号码
///
/// ChargeTermID 为空时,表示对被叫用户号码计费;
/// ChargeTermID 为非空时,表示对计费用户号码计费。
/// </summary>
public string ChargeTermID
{
get
{
return this._ChargeTermID;
}
set
{
this._ChargeTermID = value;
}
}
/// <summary>
/// 短消息接收号码总数(≤100),用于SP 实现群发短消息。
/// </summary>
public uint DestTermIDCount
{
get
{
return this._DestTermIDCount;
}
set
{
this._DestTermIDCount = value;
}
}
/// <summary>
/// 短消息接收号码。
/// </summary>
public string[] DestTermID
{
get
{
return this._DestTermID;
}
set
{
this._DestTermID = value;
}
}
/// <summary>
/// 短消息长度
///
/// 指MsgContent 域的长度,取值大于或等于0。对于MT 消息,取值应小于或等于140
/// </summary>
public uint MsgLength
{
get
{
return this._MsgLength;
}
set
{
_MsgLength = value;
}
}
/// <summary>
/// 短消息内容
/// </summary>
public string MsgContent
{
get
{
return this._MsgContent;
}
set
{
this._MsgContent = value;
this.SetHeader();
}
}
/// <summary>
/// 保留字段
/// </summary>
public string Reserve
{
get
{
return this._Reserve;
}
set
{
this._Reserve = value;
}
}
/// <summary>
/// 产品ID =MServiceID
/// </summary>
public string ProductID
{
get { return _ProductID; }
set {
_ProductID = value;
AddTlv(TlvId.Mserviceid, _ProductID);
this.SetHeader();
}
}
public string LinkID
{
get { return _LinkID; }
set {
_LinkID = value;
AddTlv(TlvId.LinkID, _LinkID);
this.SetHeader();
}
}
public Tlv[] OtherTlvArray
{
get { return _OtherTlvArray; }
//set { _OtherTlvArray = value; }
}
public override string ToString()
{
return "[/r/n"
+ this._Header.ToString() + "/r/n"
+ string.Format
(
"/tMessageBody:"
+ "/r/n/t/tMsgType: {0}"
+ "/r/n/t/tNeedReport: {1}"
+ "/r/n/t/tPriority: {2}"
+ "/r/n/t/tServiceID: {3}"
+ "/r/n/t/tFeeType: {4}"
+ "/r/n/t/tFeeCode: {5}"
+ "/r/n/t/tFixedFee: {6}"
+ "/r/n/t/tMsgFormat: {7}"
+ "/r/n/t/tValidTime: {8}"
+ "/r/n/t/tAtTime: {9}"
+ "/r/n/t/tSrcTermID: {10}"
+ "/r/n/t/tChargeTermID: {11}"
+ "/r/n/t/tDestTermIDCount: {12}"
+ "/r/n/t/tDestTermID: {13}"
+ "/r/n/t/tMsgLength: {14}"
+ "/r/n/t/tMsgContent: {15}"
+ "/r/n/t/tReserve: {16}"
+ "/r/n/t/tProductID: {17}"
+ "/r/n/t/tLinkID: {18}"
+ "/r/n/t/tOtherTlvArray: {19}"
, this._MsgType
, this._NeedReport
, this._Priority
, this._ServiceID
, this._FeeType
, this._FeeCode
, this._FixedFee
, this._MsgFormat
, this._ValidTime
, this._AtTime
, this._SrcTermID
, this._ChargeTermID
, this._DestTermIDCount
, String.Join(",", this._DestTermID)
, this._MsgLength
, this._MsgContent
, this._Reserve
, this._ProductID
, this._LinkID
, this._OtherTlvArray.ToString()
)
+ "/r/n]";
}
}
public class Submit_Resp
{
private MessageHeader _Header;
private string _MsgID;
private uint _Result;
public const int BodyLength = 10 + 4;
/// <summary>
/// 短消息流水号
/// </summary>
public string MsgID
{
get
{
return this._MsgID;
}
}
/// <summary>
/// 请求返回结果
/// </summary>
public uint Result
{
get
{
return this._Result;
}
}
public MessageHeader Header
{
get
{
return this._Header;
}
}
public 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);
//string s = null;
MsgId 10
//i += MessageHeader.Length;
//buffer = new byte[10];
//Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
//s = Encoding.ASCII.GetString(buffer).Trim();
//s = s.Substring(0, s.IndexOf('/0'));
//this._MsgID = s;
//Msg_Id
i += MessageHeader.Length;
buffer = new byte[10];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._MsgID = System.BitConverter.ToString(buffer);
// string test = System.BitConverter.ToString(buffer);
// System.Console.WriteLine("Submit_Resp=" + test);
// Array.Reverse(buffer);
// this._MsgID = BitConverter.ToUInt32(buffer, 0);
;
//Result
i += 10;
buffer = new byte[4];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
Array.Reverse(buffer);
this._Result = BitConverter.ToUInt32(buffer, 0);
}
public override string ToString()
{
return string.Format("Header={0} Msg_Id={1} tResult={2}"
, this._Header.ToString()
, this._MsgID
, this._Result);
}
}
public class Deliver
{
private ulong _MsgID;
/// <summary>
/// 短消息流水号
/// </summary>
public ulong MsgID
{
get{ return _MsgID;}
}
private uint _IsReport;
/// <summary>
/// 是否为状态报告
///
/// 0=不是状态报告;
/// 1=是状态报告;
/// </summary>
public uint IsReport
{
get{ return _IsReport;}
}
private uint _MsgFormat;
/// <summary>
/// 短消息格式
///
/// 0=ASCII 编码;
/// 3=短消息写卡操作
/// 4=二进制短消息;
/// 8=UCS2 编码;
/// 15=GB18030 编码;
/// 246(F6)=(U)SIM 相关消息;
/// </summary>
public uint MsgFormat
{
get{ return _MsgFormat;}
}
private string _RecvTime;
/// <summary>
/// 短消息接收时间
///
/// 格式为YYYYMMDDHHMMSS(年年年年月月日日时时分分秒秒
/// </summary>
public string RecvTime
{
get{ return _RecvTime;}
}
private string _SrcTermID;
/// <summary>
/// 短消息发送号码
/// </summary>
public string SrcTermID
{
get{return _SrcTermID;}
}
private string _DestTermID;
/// <summary>
/// 短消息接收号码
///
/// 格式为“118+SP 服务代码+其它(可选)
/// </summary>
public string DestTermID
{
get{return _DestTermID;}
}
private uint _MsgLength;
/// <summary>
/// 短消息长度
/// </summary>
public uint MsgLength
{
get{return _MsgLength;}
}
private string _MsgContent;
/// <summary>
/// 短消息内容
/// </summary>
public string MsgContent
{
get{return _MsgContent;}
}
private byte[] _Report;
/// <summary>
/// 状态报告
/// </summary>
public byte[] Report
{
get { return _Report; }
}
private string _Reserve;
/// <summary>
/// 保留
/// </summary>
public string Reserve
{
get{return _Reserve;}
}
private string _LinkID;
public string LinkID
{
get { return _LinkID; }
}
private uint _TP_udhi;
public uint TP_udhi
{
get { return _TP_udhi; }
}
//private string _ReportMsgID;
//public string ReportMsgID
//{
// get { return _ReportMsgID; }
//}
private Tlv[] _OtherTlv;
public Tlv[] OtherTlv
{
get { return _OtherTlv; }
}
private MessageHeader _Header;
public MessageHeader Header
{
get
{
return this._Header;
}
}
public const int FixedBodyLength = 10 // MsgId Octet String 信息标识。
+ 1 // IsReport Unsigned Integer 是否为状态报告。
+ 1 // MsgFormat Unsigned Integer 短消息格式。
+ 14 // RecvTime Octet String 短消息接收时间
+ 21 // SrcTermID Unsigned String 短消息发送号码。
+ 21 // DestTermID Unsigned String 短消息接收号码
+ 1 // MsgLength Unsigned Integer 短消息长度。
//MsgLength // MsgContent Octet String 短消息内容。
+ 8; // Reserve Octet String 保留。
// tlv
private int _BodyLength;
public int BodyLength
{
get
{
return this._BodyLength;
}
}
public 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);
string s = null;
//MsgId 10
//i += MessageHeader.Length;
//buffer = new byte[10];
//Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
//s = Encoding.ASCII.GetString(buffer).Trim();
//s = s.Substring(0, s.IndexOf('/0'));
//this._MsgID = s;
i += MessageHeader.Length;
buffer = new byte[10];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
Array.Reverse(buffer);
this._MsgID = BitConverter.ToUInt32(buffer, 0);
//IsReport 1
i += 10;
this._IsReport = (uint)bytes[i++];
this._MsgFormat = (uint)bytes[i++];
//RecvTime 14
buffer = new byte[14];
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._RecvTime = s;
//SrcTermID 21
i += 14;
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._SrcTermID = s;
//DestTermID 21
i += 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'));
this._DestTermID = s;
//MsgLength 1
i += 21;
this._MsgLength = (uint)bytes[i++];
//MsgContent
buffer = new byte[this._MsgLength];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
if (this._IsReport == 1)
{ ///状态报告 保存至Report
this._MsgContent = "";
this._Report = new byte[_MsgLength];
Buffer.BlockCopy(buffer, 0, _Report, 0, _Report.Length);
}
else
{
///短信 保存至Msg_Content
switch (this._MsgFormat)
{
case 8:
this._MsgContent = Encoding.BigEndianUnicode.GetString(buffer).Trim();
break;
case 15: //gb2312
this._MsgContent = Encoding.GetEncoding("gb2312").GetString(buffer).Trim();
break;
case 0: //ascii
case 3: //短信写卡操作
case 4: //二进制信息
default:
this._MsgContent = Encoding.ASCII.GetString(buffer).ToString();
break;
}
}
//Reserve 8
i += (int)this._MsgLength;
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._Reserve = s;
//tlv --剩余全部
i += 8;
// buffer = new byte[bytes.Length - i];
// Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
ArrayList tmptlv = new ArrayList();
for (; i < bytes.Length; )
{
//Tag 2
buffer = new byte[2];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
Array.Reverse(buffer);
short tlv_Tag = BitConverter.ToInt16(buffer, 0);
//Length 2
i += 2;
buffer = new byte[2];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
Array.Reverse(buffer);
short tlv_Length = BitConverter.ToInt16(buffer, 0);
i += 2;
String tlv_Value = "";
if (tlv_Tag == TlvId.Mserviceid || tlv_Tag == TlvId.SrcTermPseudo
|| tlv_Tag == TlvId.DestTermPseudo
|| tlv_Tag == TlvId.ChargeTermPseudo
|| tlv_Tag == TlvId.LinkID)
{
buffer = new byte[tlv_Length];
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'));
tlv_Value = s;
i += tlv_Length;
}
else
{
tlv_Value=((uint)bytes[i++]).ToString();
}
if (tlv_Tag == (short)TlvId.TP_udhi)
{
this._TP_udhi = uint.Parse(tlv_Value);
}
else if (tlv_Tag == (short)TlvId.LinkID)
{
this._LinkID = tlv_Value;
}
else
{
tmptlv.Add(new Tlv(tlv_Tag, tlv_Value));
}
if (tmptlv.Count > 0)
{
this._OtherTlv = new Tlv[tmptlv.Count];
int j = 0;
foreach (Object tmp in tmptlv)
{
this.OtherTlv[j++] = (Tlv)tmp;
}
}
}
}
public override string ToString()
{
return "[/r/n"
+ this._Header.ToString() + "/r/n"
+ string.Format
(
"/tMessageBody:"
+ "/r/n/t/tMsgID: {0}"
+ "/r/n/t/tIsReport: {1}"
+ "/r/n/t/tMsgFormat: {2}"
+ "/r/n/t/tRecvTime: {3}"
+ "/r/n/t/tSrcTermID: {4}"
+ "/r/n/t/tDestTermID: {5}"
+ "/r/n/t/tMsgLength: {6}"
+ "/r/n/t/tMsgContent: {7}"
+ "/r/n/t/tReserve: {8}"
+ "/r/n/t/tLinkID: {9}"
+ "/r/n/t/tTP_udhi: {10}"
+ "/r/n/t/tOtherTlv: {11}"
, this._MsgID
, this._IsReport
, this._MsgFormat
, this._RecvTime
, this._SrcTermID
, this._DestTermID
, this._MsgLength
, this._MsgContent
, this._Reserve
, this._LinkID
, this._TP_udhi
, this._OtherTlv.ToString()
)
+ "/r/n]";
}
}
public class Deliver_Resp
{
private MessageHeader _Header;
private ulong _MsgID;
private uint _Result;
public const int Bodylength = 10 + 4;
private uint _Sequence_Id;
public Deliver_Resp(ulong MsgID, uint Result,uint Sequence_Id)
{
this._MsgID = MsgID;
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, SMGP3_RequestId.Deliver_Resp, _Sequence_Id);
buffer = this._Header.ToBytes();
Buffer.BlockCopy(buffer, 0, bytes, 0, buffer.Length);
//MsgID 10
i += MessageHeader.Length;
//buffer = Encoding.ASCII.GetBytes(this._MsgID);
// Buffer.BlockCopy(buffer, 0, bytes, i, buffer.Length);
buffer = BitConverter.GetBytes(this._MsgID);
Array.Reverse(buffer);
buffer.CopyTo(bytes, i);
//Status 4
i += 10;
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/tMsgID: {0}"
+ "/r/n/tResult: {1}"
+ "/r/n]"
, this._MsgID
, this._Result
);
}
}
public class Active_Test
{
private MessageHeader _Header;
public MessageHeader Header
{
get
{
return this._Header;
}
}
public Active_Test(uint Sequence_Id)
{
this._Header = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Active_Test, Sequence_Id);
}
public byte[] ToBytes()
{
return this._Header.ToBytes();
}
public override string ToString()
{
return this._Header.ToString();
}
}
public class Active_Test_Resp
{
private MessageHeader _Header;
//private byte _Reserved;
//public byte Reserved
//{
// get
// {
// return this._Reserved;
// }
//}
public MessageHeader Header
{
get
{
return this._Header;
}
}
// public const int BodyLength = 1;
public Active_Test_Resp(uint Sequence_Id)
{
// this._Reserved = 1;
this._Header = new MessageHeader(MessageHeader.Length, SMGP3_RequestId.Active_Test_Resp, Sequence_Id);
}
public Active_Test_Resp(byte[] bytes)
{
//header
byte[] buffer = new byte[MessageHeader.Length];
Buffer.BlockCopy(bytes, 0, buffer, 0, buffer.Length);
this._Header = new MessageHeader(buffer);
}
public byte[] ToBytes()
{
return this._Header.ToBytes();
}
public override string ToString()
{
return this._Header.ToString();
}
}
public class Query
{
private MessageHeader _Header;
private string _QueryTime; // 8 Octet String 时间YYYYMMDD(精确至日)。
private uint _QueryType; // 1 Unsigned Integer 查询类别:
// 0:总数查询;
// 1:按业务类型查询。
private string _QueryCode; // 10 Octet String 查询码。
public MessageHeader Header
{
get
{
return this._Header;
}
}
public string QueryTime
{
get
{
return this._QueryTime;
}
}
public uint QueryType
{
get
{
return this._QueryType;
}
}
public string QueryCode
{
get
{
return this._QueryCode;
}
}
public const int BodyLength = 8 + 1 + 10;
public Query
(
DateTime Time
, uint Query_Type
, string Query_Code
, uint Sequence_Id
)
{
this._QueryTime = Util.Get_YYYYMMDD_String(Time);
this._QueryType = Query_Type;
this._QueryCode = Query_Code;
this._Header = new MessageHeader((uint)(MessageHeader.Length + BodyLength), SMGP3_RequestId.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._QueryTime);
buffer.CopyTo(bytes, i);
//Query_Type 1
i += 8;
bytes[i++] = (byte)this._QueryType;
//Query_Code 10
buffer = new byte[10];
buffer = Encoding.ASCII.GetBytes(this._QueryCode);
buffer.CopyTo(bytes, i);
return bytes;
}
public override string ToString()
{
return "[/r/n"
+ this._Header.ToString() + "/r/n"
+ string.Format
(
"/tMessageBody:"
+ "/r/n/t/tQueryCode: {0}"
+ "/r/n/t/tQueryType: {1}"
+ "/r/n/t/tQueryTime: {2}"
+ "/r/n]"
, this._QueryCode
, this._QueryType
, this._QueryTime
)
+ "/r/n]";
}
}
public class Query_Resp
{
public MessageHeader Header
{
get
{
return this._Header;
}
}
public string QueryTime
{
get
{
return this._QueryTime;
}
}
public uint QueryType
{
get
{
return this._QueryType;
}
}
public string QueryCode
{
get
{
return this._QueryCode;
}
}
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 _QueryTime; // 8 Octet String 时间(精确至日)。
private uint _QueryType; // 1 Unsigned Integer 查询类别:
// 0:总数查询;
// 1:按业务类型查询。
private string _QueryCode; // 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 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._QueryTime = Encoding.ASCII.GetString(buffer);
//Query_Type 1
i += 8;
this._QueryType = (uint)bytes[i++];
//Query_Code 10
buffer = new byte[10];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._QueryCode = 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/tQueryCode: {9}"
+ "/r/n/t/tQueryType: {10}"
+ "/r/n/t/tQueryTime: {11}"
, 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._QueryCode
, this._QueryType
, this._QueryTime
)
+ "/r/n]";
}
}
public class MsgContent
{
public const int BodyLength = 10 + 3+3 + 10 + 10 + 7 + 3+20;
private string _MsgID; // 10 Octet String 信息标识。SP提交短信(CMPP_SUBMIT)操作时,与SP相连的ISMG产生的Msg_Id。
private string _Sub; //3
private string _Dlvrd; //3
private string _Submit_date; //10
private string _Done_date; //10
private string _Stat; // 7
private string _Err; //3
private string _Txt; //3+17
//public MsgContent(string msgcontent)
//{
// string s=null;
// // msgcontent.
// //s = s.Substring(0, s.IndexOf('/0'));
// int startIndex=msgcontent.IndexOf("id:");
// int lastIndex=msgcontent.IndexOf("sub:");
// if (startIndex >= 0 && lastIndex > startIndex)
// s = msgcontent.Substring(startIndex, lastIndex);
// int i = 0;
// byte[] bytes=Encoding.ASCII.GetBytes(s);
// byte[] buffer = new byte[10];
// Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
// Array.Reverse(buffer);
// this._MsgID = BitConverter.ToUInt32(buffer, 0);
// startIndex = lastIndex;
// lastIndex = msgcontent.IndexOf("dlvrd:");
// if (startIndex >= 0 && lastIndex > startIndex)
// s = msgcontent.Substring(startIndex, lastIndex);
// this._Sub = s;
// startIndex = lastIndex;
// lastIndex = msgcontent.IndexOf("dlvrd:");
// if (startIndex >= 0 && lastIndex > startIndex)
// s = msgcontent.Substring(startIndex, lastIndex);
// this._Sub = s;
//}
public MsgContent(byte[] bytes)
{
if (bytes.Length >= BodyLength)
{
///“id:IIIIIIIIII sub:SSS dlvrd:DDD Submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DDDDDDD err:E Text:……
string tag="";
int i = 0;
//_MsgID 10
tag="id:";
i += tag.Length;
byte[] buffer = new byte[10];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._MsgID = System.BitConverter.ToString(buffer);
// string test = System.BitConverter.ToString(buffer);
// System.Console.WriteLine("MsgContent=" + test);
//Array.Reverse(buffer);
//this._MsgID = BitConverter.ToUInt32(buffer, 0);
//_Sub 3
i += 10;
tag = "sub:";
i += tag.Length;
buffer = new byte[3];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Sub = Encoding.ASCII.GetString(buffer);
//_Dlvrd 3
i += 3;
tag = " dlvrd:";
i += tag.Length;
buffer = new byte[3];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Dlvrd = Encoding.ASCII.GetString(buffer);
//_Submit_date 10
i += 3;
tag = " Submit date:";
i += tag.Length;
buffer = new byte[10];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Submit_date = Encoding.ASCII.GetString(buffer);
//_Done_date 10
i += 10;
tag = " done date:";
i += tag.Length;
buffer = new byte[10];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Done_date = Encoding.ASCII.GetString(buffer);
//_Stat 7
i += 10;
tag = " stat:";
i += tag.Length;
buffer = new byte[7];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Stat = Encoding.ASCII.GetString(buffer);
//_Err 3
i += 7;
tag = " err:";
i += tag.Length;
buffer = new byte[3];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Err = Encoding.ASCII.GetString(buffer);
//_Txt 20
i += 3;
tag = " txt:";
i += tag.Length;
buffer = new byte[bytes.Length - i];
Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
this._Txt = Encoding.ASCII.GetString(buffer);
//i += 3;
//buffer = new byte[bytes.Length-i];
//Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length);
//this._Txt = Encoding.ASCII.GetString(buffer);
}
}
/// <summary>
/// 状态报告对应原短消息的MsgID
/// </summary>
public string MsgID
{
get { return _MsgID; }
}
/// <summary>
/// 取缺省值001
/// </summary>
public string Sub
{
get { return _Sub; }
}
/// <summary>
/// 取缺省值001
/// </summary>
public string Dlvrd
{
get { return _Dlvrd; }
}
/// <summary>
/// 短消息提交时间(格式:年年月月日日时时分分,例如010331200000)
/// </summary>
public string Submit_date
{
get { return _Submit_date; }
}
/// <summary>
/// 短消息下发时间(格式:年年月月日日时时分分,例如010331200000)
/// </summary>
public string Done_date
{
get { return _Done_date; }
}
/// <summary>
/// 短消息的最终状态
/// </summary>
public string Stat
{
get { return _Stat; }
}
/// <summary>
/// 错误代码表
/// </summary>
public string Err
{
get { return _Err; }
}
/// <summary>
///
/// </summary>
public string Txt
{
get { return _Txt; }
}
public override string ToString()
{
return string.Format
(
"[/r/nMessageBody:"
+ "/r/n/tBodyLength: {0}"
+ "/r/n/tMsgID: {1}"
+ "/r/n/tSub: {2}"
+ "/r/n/tDlvrd: {3}"
+ "/r/n/tSubmit_date: {4}"
+ "/r/n/tDone_date: {5}"
+ "/r/n/tStat: {6}"
+ "/r/n/tErr: {7}"
+ "/r/n/tTxt: {8}"
+ "/r/n]"
, MsgContent.BodyLength
, this._MsgID
, this._Sub
, this._Dlvrd
, this._Submit_date
, this._Done_date
, this._Stat
, this._Err
, this._Txt
);
}
}
public class TlvId
{
public static short TP_pid = 0x0001;
public static short TP_udhi = 0x0002;
public static short LinkID = 0x0003;
public static short ChargeUserType = 0x0004;
public static short ChargeTermType = 0x0005;
public static short ChargeTermPseudo = 0x0006;
public static short DestTermType = 0x0007;
public static short DestTermPseudo = 0x0008;
public static short PkTotal = 0x0009;
public static short PkNumber = 0x000A;
public static short SubmitMsgType = 0x000B;
public static short SPDealReslt = 0x000C;
public static short SrcTermType = 0x000D;
public static short SrcTermPseudo = 0x000E;
public static short NodesCount = 0x000F;
public static short MsgSrc = 0x0010;
public static short SrcType = 0x0011;
public static short Mserviceid = 0x0012;
}
public class Tlv
{
public short Tag;
public short Length;
public String Value;
public byte[] TlvBuf;
public Tlv(short tag, string value)
{
this.Tag = tag;
this.Length = (short)value.Length;
this.Value = value;
if (tag == TlvId.Mserviceid || tag == TlvId.MsgSrc
|| tag == TlvId.SrcTermPseudo || tag == TlvId.DestTermPseudo
|| tag == TlvId.ChargeTermPseudo || tag == TlvId.LinkID)
{
//参数为oct string
int i = 0;
this.TlvBuf = new byte[4 + this.Length];
//Tag 2
byte[] buffer = BitConverter.GetBytes((short)Tag);
Array.Reverse(buffer);
buffer.CopyTo(TlvBuf, i);
//Length 2
i += 2;
buffer = BitConverter.GetBytes(Length);
Array.Reverse(buffer);
buffer.CopyTo(TlvBuf, i);
//Value Length
i += 2;
buffer = Encoding.ASCII.GetBytes(this.Value);
Buffer.BlockCopy(buffer, 0, TlvBuf, i, buffer.Length);
}
else
{
int i = 0;
this.TlvBuf = new byte[4 + 1];
//Tag 2
byte[] buffer = BitConverter.GetBytes((short)Tag);
Array.Reverse(buffer);
buffer.CopyTo(TlvBuf, i);
//Length 2
i += 2;
buffer = BitConverter.GetBytes(Length);
Array.Reverse(buffer);
buffer.CopyTo(TlvBuf, i);
//Value 1
i += 2;
uint tmp = 0;
uint.TryParse(value, out tmp);
TlvBuf[i] = (byte)tmp;
}
}
}
}
//------------------------------------------------------------------------------
//文件StateDictionary.cs
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace AsiaINFO.SMS.SMGP3
{
/// <summary>
/// 状态字典
/// </summary>
public class StateDictionary
{
/// <summary>
/// Status 请求返回结果。响应包用来向请求包返回成功信息或者失败原因。
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static string stateRespDictionary(uint state)
{
string result = "结果:";
switch (state)
{
case 0: result += "成功"; break;
case 1: result += "系统忙"; break;
case 2: result += "超过最大连接数"; break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9: result += "保留"; break;
case 10: result +="消息结构错";break;
case 11: result +="命令字错";break;
case 12: result +="序列号重复";break;
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19: result +="保留";break;
case 20: result +="IP 地址错";break;
case 21: result +="认证错";break;
case 22: result +="版本太高";break;
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29: result +="保留";break;
case 30: result +="非法消息类型(MsgType)";break;
case 31: result +="非法优先级(Priority)";break;
case 32: result +="非法资费类型(FeeType)";break;
case 33: result +="非法资费代码(FeeCode)";break;
case 34: result +="非法短消息格式(MsgFormat)";break;
case 35: result +="非法时间格式";break;
case 36: result +="非法短消息长度(MsgLength)";break;
case 37: result +="有效期已过";break;
case 38: result +="非法查询类别(QueryType)";break;
case 39: result +="路由错误";break;
case 40: result +="非法包月费/封顶费(FixedFee)";break;
case 41: result +="非法更新类型(UpdateType";break;
case 42: result +="非法路由编号(RouteId)";break;
case 43: result +="非法服务代码(ServiceId)";break;
case 44: result +="非法有效期(ValidTime)";break;
case 45: result +="非法定时发送时间(AtTime)";break;
case 46: result +="非法发送用户号码(SrcTermId)";break;
case 47: result +="非法接收用户号码(DestTermId)";break;
case 48: result +="非法计费用户号码(ChargeTermId)";break;
case 49: result +="非法SP 服务代码(SPCode)";break;
case 50:
case 51:
case 52:
case 53:
case 54:
case 55: result +=" 其它用途";break;
case 56: result +="非法源网关代码(SrcGatewayID)";break;
case 57: result +="非法查询号码(QueryTermID)";break;
case 58: result +="没有匹配路由";break;
case 59: result +="非法SP 类型(SPType)";break;
case 60: result +="非法上一条路由编号(LastRouteID)";break;
case 61: result +="非法路由类型(RouteType)";break;
case 62: result +="非法目标网关代码(DestGatewayID)";break;
case 63: result +="非法目标网关IP(DestGatewayIP)";break;
case 64: result +="非法目标网关端口(DestGatewayPort)";break;
case 65: result +="非法路由号码段(TermRangeID)";break;
case 66: result +="非法终端所属省代码(ProvinceCode)";break;
case 67: result +="非法用户类型(UserType)";break;
case 68: result +="本节点不支持路由更新";break;
case 69: result +="非法SP 企业代码(SPID)";break;
case 70: result +="非法SP 接入类型(SPAccessType)";break;
case 71: result +="路由信息更新失败";break;
case 72: result +="非法时间戳(Time)";break;
case 73: result += "非法业务代码(MServiceID)"; break;
case 74: result += "SP 禁止下发时段"; break;
case 75: result += "SP 发送超过日流量"; break;
case 76: result += "SP 帐号过有效期"; break;
case 112:
case 113:
case 114:
case 115:
case 116: result += "其它用途"; break;
default: result += "未知错误" ; break;
}
return result;
}
}
}
//------------------------------------------------------------------------------
//文件SyncEvents.cs
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace AsiaINFO.SMS.SMGP3
{
/// <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.SMGP3
{
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;
}
}
}