短信猫软件的实现(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: get2: {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'); //去掉结尾F8: return result;9: }
这样,读取ServiceCenterAddress属性即可得到短消息中心地址。程序可读取示例消息中心:8613010452500
- OA(发送方地址)部分解码:
字段:originatorAddress;属性:OriginatorAddress。
解码时,先把OA部分PDU串(0BA15150800576F7)写入字段originatorAddress。同样,从属性读取到的即为发送方的手机号码。
对应get访问器代码:
1: get2: {3: int len = Convert.ToInt32(originatorAddress.Substring(0, 2),16); //十六进制字符串转为整形数据4: string result = string.Empty;5: if (len % 2 == 1) //号码长度是奇数,长度加1 编码时加了F6: {7: len++;
8: }
9: result = originatorAddress.Substring(4, len); //去掉头部
10: result = ParityChange(result).TrimEnd('F', 'f'); //奇偶互换,并去掉结尾F11:
12: return result;13: }
这样,读取OriginatorAddress属性即可得到短消息中心地址。程序可读取示例消息中心:15050850677
- SCTS(服务中心时间戳)部分解码:
字段:serviceCenterTimeStamp;属性:ServiceCenterTimeStamp。
解码时,先把SCTS部分PDU串(01112081600423)写入字段serviceCenterTimeStamp。同样,从属性读取到的即为消息中心收到信息的时间。
对应get访问器代码:
1: get2: {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: get2: {
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部分编解码。有兴趣可以下载附件,自己添加。
附件:工程项目文件