查看: 9427|回复: 0
打印 上一主题 下一主题

C#实现PDU格式解码程序

[复制链接]
跳转到指定楼层
楼主
发表于 2014-3-7 19:09:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
昨天简单完成了解码部分,今天加入编码部分(同一个类中)。方式和编码部分类似,利用属性对字段访问的特点,把解码程序写在属性访问部分。解码的函数只需读取这些属性值即可完成PDU解码工作。

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

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

有关收到信息PDU格式解析参考:
PDU格式短信编码的原理

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

0891683110402505F0240BA15111181394F4000801112081600423044F60597D

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串(0BA15111181394F4)写入字段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属性即可得到短消息中心地址。程序可读取示例消息中心:15118131494
  • 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("0891683110402505F0240BA15111181394F4000801112081600423044F60597D", out s1, out s2, out s3, out s4);(peDUEncoding pe=new PDUEncoding();)
输出:
s1:8613010452500
s2:15118131494
s2:你好
s3:20101102180640
成功!

至此编码部分简单完成
实现的比较简单,没有实现7bit及8bit部分编解码。有兴趣可以下载附件,自己添加。
项目工程.rar (134.42 KB, 下载次数: 3134)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|小黑屋|未来时代科技 ( 粤ICP备12044031号-1

GMT+8, 2024-11-23 01:52 , Processed in 0.065266 second(s), 33 queries .

Powered by WLSD X3.1

© 2013-2014 WLSD Inc.

快速回复 返回顶部 返回列表
 
【电话】(15118131494)
【QQ】 未来时代科技01 售前咨询
【QQ】 未来时代科技02 售后技术
【旺旺】 请问有什么可以帮到您?不在线可留言.
【邮箱】
inextera@sina.com
【地址】 (深圳市龙岗坂田扬马小区)