C#:PDU格式短信编解码(二)长短信拆分

/* ----------------------------------------------------------
文件名称:Split.cs

作者:秦建辉

MSN:splashcn@msn.com
QQ:36748897

博客:http://blog.csdn.net/jhqin

开发环境:
    Visual Studio V2010
    .NET Framework 4 Client Profile

版本历史:    
    V1.0	2011年08月19日
			短信拆分部分
------------------------------------------------------------ */
using System;
using System.Collections.Generic;

namespace Splash.Phone
{
    /// <summary>
    /// 短信拆分部分
    /// </summary>
    public partial class SMS
    {
        /// <summary>
        /// 编码方案对应的最大用户数据长度
        /// </summary>
        private enum EnumUDL
        {
            BIT7UDL = 160,  // 7Bit编码允许的最大字符数
            BIT8UDL = 140,  // 8Bit编码允许的最大字节数
            UCS2UDL = 70    // UCS2编码允许的最大字符数
        }

        /// <summary>
        /// 用户数据内容拆分
        /// </summary>
        /// <param name="UDC">用户数据内容</param>
        /// <param name="UDH">用户数据头</param>
        /// <param name="DCS">编码方案</param>
        /// <returns>拆分内容列表</returns>
        private List<String> UDCSplit(String UDC, PDUUDH[] UDH = null, EnumDCS DCS = EnumDCS.UCS2)
        {   // 统计用户数据头长度
            Int32 UDHL = GetUDHL(UDH);

            if (DCS == EnumDCS.BIT7)
            {   // 7-Bit编码
                // 计算剩余房间数
                Int32 Room = (Int32)EnumUDL.BIT7UDL - (UDHL * 8 + 6) / 7;
                if (Room < 1)
                {
                    if (String.IsNullOrEmpty(UDC))
                        return new List<String>() { UDC };
                    else
                        return null;    // 超出范围
                }

                if (SeptetsLength(UDC) <= Room)
                {
                    return new List<String>() { UDC };
                }
                else
                {   // 需要拆分成多条短信
                    if (UDHL == 0) UDHL++;
                    if (mCSMIEI == EnumCSMIEI.BIT8)
                        UDHL += 5;  // 1字节消息参考号
                    else
                        UDHL += 6;  // 2字节消息参考号

                    // 更新剩余房间数
                    Room = (Int32)EnumUDL.BIT7UDL - (UDHL * 8 + 6) / 7;
                    if (Room < 1) return null;   // 超出范围

                    List<String> CSM = new List<String>();                    
                    Int32 i = 0;
                    while (i < UDC.Length)
                    {
                        Int32 Step = SeptetsToChars(UDC, i, Room);
                        if (i + Step < UDC.Length)
                            CSM.Add(UDC.Substring(i, Step));                        
                        else
                            CSM.Add(UDC.Substring(i));

                        i += Step;
                    }

                    return CSM;
                }
            }
            else
            {   // UCS2编码
                // 计算剩余房间数
                Int32 Room = ((Int32)EnumUDL.BIT8UDL - UDHL) >> 1;
                if(Room < 1)
                {
                    if (String.IsNullOrEmpty(UDC))
                        return new List<String>() { UDC };
                    else
                        return null;    // 超出范围
                }

                if (UDC == null || UDC.Length <= Room)
                {
                    return new List<String>() { UDC };
                }
                else
                {   // 需要拆分成多条短信
                    if (UDHL == 0) UDHL++;
                    if (mCSMIEI == EnumCSMIEI.BIT8)
                        UDHL += 5;  // 1字节消息参考号
                    else
                        UDHL += 6;  // 2字节消息参考号

                    // 更新剩余房间数
                    Room = ((Int32)EnumUDL.BIT8UDL - UDHL) >> 1;
                    if (Room < 1) return null;  // 超出范围

                    List<String> CSM = new List<String>();
                    for (Int32 i = 0; i < UDC.Length; i += Room)
                    {
                        if (i + Room < UDC.Length)
                            CSM.Add(UDC.Substring(i, Room));
                        else
                            CSM.Add(UDC.Substring(i));
                    }

                    return CSM;
                }
            }
        }

        /// <summary>
        /// 用户数据内容拆分
        /// </summary>
        /// <param name="UDC">用户数据内容</param>
        /// <param name="UDH">用户数据头</param>
        /// <returns>拆分内容列表</returns>
        private List<Byte[]> UDCSplit(Byte[] UDC, PDUUDH[] UDH = null)
        {   // 统计用户数据头长度
            Int32 UDHL = GetUDHL(UDH);
            
            // 8-Bit编码
            if (UDC == null || UDC.Length <= (Int32)EnumUDL.BIT8UDL - UDHL)
            {   // 不需要拆分
                return new List<Byte[]>() { UDC };
            }
            else
            {   // 需要拆分成多条短信
                if (UDHL == 0) UDHL++;
                if (mCSMIEI == EnumCSMIEI.BIT8)
                    UDHL += 5;  // 1字节消息参考号
                else
                    UDHL += 6;  // 2字节消息参考号

                // 短信内容拆分
                List<Byte[]> CSM = new List<Byte[]>();
                Int32 Step = (Int32)EnumUDL.BIT8UDL - UDHL;
                for (Int32 i = 0; i < UDC.Length; i += Step)
                {
                    CSM.Add((Byte[])UDC.SubArray(i, Step));
                }

                return CSM;
            }
        }

        /// <summary>
        /// 用户数据头长度
        /// </summary>
        /// <param name="UDH">用户数据头</param>
        /// <returns>用户数据头编码字节数</returns>
        private static Int32 GetUDHL(PDUUDH[] UDH)
        {
            if (UDH == null || UDH.Length == 0) return 0;

            Int32 UDHL = 1;     // 加上1字节的用户数据头长度
            foreach (PDUUDH IE in UDH)
            {
                UDHL += IE.IED.Length + 2;  // 信息元素标识+信息元素长度+信息元素数据
            }

            return UDHL;
        }

        /// <summary>
        /// 计算字符串需要的7-Bit编码字节数
        /// </summary>
        /// <param name="source">字符串</param>
        /// <returns>7-Bit编码字节数</returns>
        private static Int32 SeptetsLength(String source)
        {
            if (String.IsNullOrEmpty(source)) return 0;
            
            Int32 Length = source.Length;
            foreach (Char Letter in source)
            {
                UInt16 Code = Convert.ToUInt16(Letter);
                if (UCS2ToBIT7.ContainsKey(Code))
                {
                    if (UCS2ToBIT7[Code] > 0xFF) Length++;
                }
            }

            return Length;
        }

        /// <summary>
        /// 判断字符串是否在GSM缺省字符集内
        /// </summary>
        /// <param name="source">要评估的字符串</param>
        /// <returns>
        ///     true:在GSM缺省字符集内,可以使用7-Bit编码
        ///     false:不在GSM缺省字符集内,只能使用UCS2编码
        /// </returns>
        private static Boolean isGSMString(String source)
        {
            if (String.IsNullOrEmpty(source)) return true;

            foreach (Char Letter in source)
            {
                UInt16 Code = Convert.ToUInt16(Letter);
                if (!(isBIT7Same(Code) || UCS2ToBIT7.ContainsKey(Code)))
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 将7-Bit编码字节数换算成UCS2编码字符数
        /// </summary>
        /// <param name="source">字符串</param>
        /// <param name="index">起始索引号</param>
        /// <param name="septets">要换算的7-Bit编码字节数</param>
        /// <returns>UCS2编码字符数</returns>
        private static Int32 SeptetsToChars(String source, Int32 index, Int32 septets)
        {
            if (String.IsNullOrEmpty(source)) return 0;

            Int32 Count = 0;
            Int32 i = index;
            for (; i < source.Length; i++)
            {
                UInt16 Code = Convert.ToUInt16(source[i]);
                if (UCS2ToBIT7.ContainsKey(Code) && UCS2ToBIT7[Code] > 0xFF)
                {
                    Count++;
                }
                
                if (++Count >= septets)
                {
                    if (Count == septets) i++;
                    break;
                }
            }

            return i - index;
        }

        /// <summary>
        /// 在用户数据头中增加长短信信息元素
        /// </summary>
        /// <param name="UDH">原始用户数据头</param>
        /// <param name="CSMMR">消息参考号</param>
        /// <param name="Total">短消息总数</param>
        /// <param name="Index">短消息序号</param>
        /// <returns>更新后的用户数据头</returns>
        private PDUUDH[] UpdateUDH(PDUUDH[] UDH, Int32 CSMMR, Int32 Total, Int32 Index)
        {
            List<PDUUDH> CSMUDH;
            if (UDH == null || UDH.Length == 0)
                CSMUDH = new List<PDUUDH>(1);
            else
                CSMUDH = new List<PDUUDH>(UDH);
            
            if (mCSMIEI == EnumCSMIEI.BIT8)
            {
                Byte[] IED = new Byte[3]{(Byte)(CSMMR & 0xFF), (Byte)Total, (Byte)(Index + 1)};
                CSMUDH.Insert(0, new PDUUDH { IEI = 0, IED = IED });
            }
            else
            {
                Byte[] IED = new Byte[4] { (Byte)((CSMMR >> 8) & 0xFF), (Byte)(CSMMR & 0xFF), (Byte)Total, (Byte)(Index + 1) };
                CSMUDH.Insert(0, new PDUUDH { IEI = 8, IED = IED });
            }

            return CSMUDH.ToArray();
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值