短信猫软件的实现(C#)<五>PDU格式解码C#实现

昨天简单完成了解码部分,今天加入编码部分(同一个类中)。方式和编码部分类似,利用属性对字段访问的特点,把解码程序写在属性访问部分。解码的函数只需读取这些属性值即可完成PDU解码工作。

手机或短信猫接收到的PDU字符串包含SCA、PDU-Type、OA、PID、DCS、SCTS、UDL、UD八个部分,每个部分包含对应字段和属性,字段中存储PDU格式编码对应段的字符串(函数先把对应字符串存入对应字段),属性读取过程写入代码,读取的值即为解码后的数据(短信内容、手机号码等)。

从PDU获取信息需读出(解码)四部分:SCA、OA、SCTS、UD,以下分别对其讲解。

有关收到信息PDU格式解析参考:
短信猫软件的实现(C#)<三>PDU格式短信解析

示例PDU串:从15050850677收到一条短信,内容“你好”。

0891683110402505F0240BA15150800576F7000801112081600423044F60597D

  • SCA(短消息服务中心)部分解码:

字段:serviceCenterAddress;属性:ServiceCenterAddress。

解码时,先把SCA部分PDU串(0891683110402505F0)写入字段serviceCenterAddress。属性访问器get部分完成解码工作。get部分代码:

1:  get
2:   {
3:      int len = Convert.ToInt32(serviceCenterAddress.Substring(0, 2));   //获取SCA长度
4:      string result = serviceCenterAddress.Substring(4, len - 4);        //去掉起头部分
5:    //ParityChange函数见上一篇的编码
6:      result = ParityChange(result);          //奇偶互换
7:      result = result.TrimEnd('F', 'f');      //去掉结尾F
8:      return result;
9:  }

这样,读取ServiceCenterAddress属性即可得到短消息中心地址。程序可读取示例消息中心:8613010452500

  • OA(发送方地址)部分解码:

字段:originatorAddress;属性:OriginatorAddress。

解码时,先把OA部分PDU串(0BA15150800576F7)写入字段originatorAddress。同样,从属性读取到的即为发送方的手机号码。

对应get访问器代码:

 1:  get
 2:   {
 3:      int len = Convert.ToInt32(originatorAddress.Substring(0, 2),16);    //十六进制字符串转为整形数据
 4:      string result = string.Empty;
 5:      if (len % 2 == 1)       //号码长度是奇数,长度加1 编码时加了F
 6:      {
 7:          len++;
 8:      }
 9:      result = originatorAddress.Substring(4, len);    //去掉头部
10:      result = ParityChange(result).TrimEnd('F', 'f');  //奇偶互换,并去掉结尾F
11:   
12:      return result;
13:  }

这样,读取OriginatorAddress属性即可得到短消息中心地址。程序可读取示例消息中心:15050850677

  • SCTS(服务中心时间戳)部分解码:

字段:serviceCenterTimeStamp;属性:ServiceCenterTimeStamp。

解码时,先把SCTS部分PDU串(01112081600423)写入字段serviceCenterTimeStamp。同样,从属性读取到的即为消息中心收到信息的时间。

对应get访问器代码:

1:  get
2:   {
3:      string result = ParityChange(serviceCenterTimeStamp);   //奇偶互换
4:      result = "20" + result.Substring(0, 12);            //年加开始的“20”
5:   
6:      return result;
7:  }

读取ServiceCenterTimeStamp属性即可得到时间字符串:20101102180640 代表:2010-11-02 18:06:44

  • UD(用户数据,短信内容)部分解码:

    字段:userData;属性:UserData。

    解码时,先把UD部分PDU串(4F60597D)写入字段UserData。同样,从属性读取到的即为短信内容。

    对应get访问器代码:

 1:  get
 2:  {
 3:      int len = Convert.ToInt32(userDataLenghth, 16) * 2;
 4:      string result = string.Empty;
 5:      //四个一组,每组译为一个USC2字符
 6:      for (int i = 0; i < len; i += 4)
 7:      {
 8:          string temp = userData.Substring(i , 4);
 9:   
10:          int byte1 = Convert.ToInt16(temp, 16);
11:   
12:          result += ((char)byte1).ToString();
13:      }
14:   
15:      return result;
16:  }

访问UserData即得段内容。示例可得到短信内容:“你好”。

  • 解码程序:

解码程序须将对应PDu编码的值赋给对应字段,然后读取各个属性即可完成解码:

 1:  /// <summary>
 2:  /// 完成手机或短信猫收到PDU格式短信的解码 暂时仅支持中文编码
 3:  /// 未用DCS部分
 4:  /// </summary>
 5:  /// <param name="strPDU">短信PDU字符串</param>
 6:  /// <param name="msgCenter">短消息服务中心 输出</param>
 7:  /// <param name="phone">发送方手机号码 输出</param>
 8:  /// <param name="msg">短信内容 输出</param>
 9:  /// <param name="time">时间字符串 输出</param>
10:  public void PDUDecoder(string strPDU, out string msgCenter, out string phone, out string msg, out string time)
11:  {
12:      int lenSCA = Convert.ToInt32(strPDU.Substring(0, 2), 16) * 2 + 2;       //短消息中心占长度
13:      serviceCenterAddress = strPDU.Substring(0, lenSCA);
14:   
15:      int lenOA = Convert.ToInt32(strPDU.Substring(lenSCA + 2, 2),16);           //OA占用长度
16:      if (lenOA % 2 == 1)                                                     //奇数则加1 F位
17:      {
18:          lenOA++;
19:      }
20:      lenOA += 4;                 //加号码编码的头部长度
21:      originatorAddress = strPDU.Substring(lenSCA + 2, lenOA);
22:   
23:      serviceCenterTimeStamp = strPDU.Substring(lenSCA + lenOA + 6, 14);
24:   
25:      userDataLenghth = strPDU.Substring(lenSCA + lenOA + 20, 2);
26:      int lenUD = Convert.ToInt32(userDataLenghth, 16) * 2;
27:      userData = strPDU.Substring(lenSCA + lenOA + 22, lenUD);
28:   
29:      msgCenter = ServiceCenterAddress;
30:      phone = OriginatorAddress;
31:      msg = UserData;
32:      time = ServiceCenterTimeStamp;
33:  }

调用程序pe.PDUDecoder("0891683110402505F0240BA15150800576F7000801112081600423044F60597D", out s1, out s2, out s3, out s4);(pe:PDUEncoding pe=new PDUEncoding();)
输出:
s1:8613010452500
s2:15050850677
s2:你好
s3:20101102180640
成功!

至此编码部分简单完成。

实现的比较简单,没有实现7bit及8bit部分编解码。有兴趣可以下载附件,自己添加。

附件:工程项目文件

posted @ 2010-11-05 16:20  给我一杯酒  阅读(8996)  评论(20编辑  收藏  举报