以下部分资料是从网上各个博客收集到的:

1、目前,发送短消息常用Text和PDU(Protocol Data Unit,协议数据单元)模式。

1>使用Text模式收发短信代码简单,实现起来十分容易,但最大的缺点是不能收发中文短信;

2>使用PDU模式不仅支持中文短信,也能发送英文短信。

2、PDU模式收发短信可以使用3种编码:

1>7-bit(用于发送普通的ASCII字符,它将一串7-bit的字符(最高位为0)编码成8-bit的数据,每8个字符可   “压缩”成7个)

2>8-bit(通常用于发送数据消息,如:图片了,铃声等等)

3>UCS2编码(用于发送Unicode字符)

在以上这三种编码方式下,PDU串的用户信息(TP-UD)段最大容量(可以发送的短消息的最大字符数)分别是160、140和70。这里,将一个英文字母、一个汉字和一个数据字节都视为一个字符。

PDU串的用户信息长度(TP-UDL),在各种编码方式下意义有所不同。7-bit编码时,指原始短消息的字符个数,而不是编码后的字节数。8-bit编码时,就是字节数。UCS2编码时,也是字节数,

等于原始短消息的字符数的两倍。如果用户信息(TP-UD)中存在一个头(基本参数的TP-UDHI为1),在所有编码方式下,用户信息长度(TP-UDL)都等于头长度与编码后字节数之和。如果采用GSM

03.42所建议的压缩算法(TP-DCS的高3位为001),则该长度也是压缩编码后字节数或头长度与压缩编码后字节数之和。

3、那ucs2编码是什么呢?由此我们去看看计算机对不同字符的编码是怎么处理的:

<1>Unicode也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS

。UCS可以看作是"Unicode Character Set"的缩写。

根据维基百科全书()的记载:历史上存在两个试图独立设计Unicode的组织,即国际标准化组织(ISO)和一个软件制造商的协会(unicode.org)。ISO开发了

ISO 10646项目,Unicode协会开发了Unicode项目。

在1991年前后,双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode2.0开始,Unicode项目采用了与ISO

10646-1相同的字库和字码。

目前两个项目仍都存在,并独立地公布各自的标准。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是10646-3:2003。

<2>UCS-2、UCS-4、BMP

UCS规定了怎么用多个字节表示各种文字。怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-7、UTF-16。

UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。下面让我们做一些简单的数学游戏:

UCS-2有2^16=65536个码位,UCS-4有2^31=2147483648个码位。

UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个plane。每个plane根据第3个字节分为256行 (rows),每行包含256个cells。当然同一行的cells只

是最后一个字节不同,其余都相同。

group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节为0的码位被称作BMP。

将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。在UCS-2的两个字节前加上两个零字节,就得到了UCS-4的BMP。而目前的UCS-4规范中还没有任何字符被分配在BMP之外

<3>UTF编码

UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下:

UCS-2编码(16进制)     UTF-8 字节流(二进制)

0000 - 007F         0xxxxxxx

0080 - 07FF         110xxxxx 10xxxxxx

0800 - FFFF         1110xxxx 10xxxxxx 10xxxxxx

例如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间,所以肯定要用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 110001 001001, 用这个比特流依次代

替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

读者可以用记事本测试一下我们的编码是否正确。

UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码,UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码,定义了一个算法。不过由于实际使用的UCS2,

或者UCS4的BMP必然小于0x10000,所以就目前而言,可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题。

<4>UTF的字节序和BOM

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,

“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?

4、了解了以上的字符编码,就更容易让我们去组织发送短信时的PDU串:

(1)用户要的内容是以UTF8传输的,我们应该把这些字符转化成unicode编码(因为短信发送的信息必须是以unicode编码)。转化编码方法有三种:

1>、通过mbstowcs()和wcstombs()这俩个函数,可以将ASCII码字符串和宽字符(Unicode)互相转化,mbstowcs函数将汉字视作两个ASCII字符,这样一个汉字就变成了两个wchar_t。原因是

mbstowcs需要我们明确的告诉他要转换的字符语言。这里需要使用setlocale函数。

要在调用以上函数前,使用setlocale()设置。如何设置呢?我们在了解一下这个函数:

char* setlocale(int category, const char* locale);

说明:

category:为locale分类,表达一种locale的领域方面,通常有下面这些预定义常量:LC_ALL、LC_COLLATE、LC_CTYPE、LC_MESSAGES、LC_MONETARY、LC_NUMERIC、LC_TIME,其中 LC_ALL 表

示所有其它locale分类的并集。

LC_COLLATE    排序信息

LC_CTYPE    字符分类信息

LC_MONETARY    货币打印信息

LC_NUMERIC    数值打印信息

LC_TIME        日期和时间打印信息

locale:为期望设定的locale名称字符串,在Linux/Unix环境下,通常以下面格式表示locale名称:language[_territory][.codeset][@modifier],language 为 ISO 639 中规定的语言代码

,territory 为 ISO 3166 中规定的国家/地区代码,codeset 为字符集名称。

在Linux下,可以使用 locale -a 命令查看系统中所有已配置的 locale。用不带选项的 locale 命令查看当前 Shell 中活动的 locale。用 locale -m 命令查看locale系统支持的所有

可用的字符集编码。

和locale相关的包叫做:locales,locale系统支持的所有可用locale在文件:/usr/share/i18n/SUPPORTED 中列出。

在Debian下,可用 dpkg-reconfigure locales 命令重新配置 locale,也可以手工修改 /etc/locale.gen 文件,然后运行 locale-gen 命令。

在Ubuntu下,修改 /var/lib/locales/supported.d/local 文件,配置新的 locale,然后运行 locale-gen 命令。

当 locale 为 NULL 时,函数只做取回当前 locale 操作,通过返回值传出,并不改变当前 locale。

当 locale 为 "" 时,根据环境的设置来设定 locale,检测顺序是:环境变量 LC_ALL,每个单独的locale分类LC_*,最后是 LANG 变量。为了使程序可以根据环境来改变活动 locale,一般

都在程序的初始化阶段加入下面代码:setlocale(LC_ALL, "")。

当C语言程序初始化时(刚进入到 main() 时),locale 被初始化为默认的 C locale,其采用的字符编码是所有本地 ANSI 字符集编码的公共部分,是用来书写C语言源程序的最小字符集(

所以才起locale名叫:C)。

当用 setlocale() 设置活动 locale 时,如果成功,会返回当前活动 locale 的全名称;如果失败,会返回 NULL。

通过这一组函数就能实现字符编码转换,但移植性不强,他涉及了系统支持的字符编码不容易实现我们想的编码。

2>、在LINUX上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用iconv命令来实现,只不过后者是针对文件的,即将指定文件从一种编码转换为另一种编码。

iconv函数族的头文件是iconv.h,使用前需包含之。

#include iconv函数族有三个函数,原型如下:

(1) iconv_t iconv_open(const char *tocode, const char *fromcode);

此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。

(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);

此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。

(3) int iconv_close(iconv_t cd); 此函数用于关闭转换句柄,释放资源。

3>、通过自己实现编码转化,这样对平台没有依赖性,只是对编码之前的传输过来的字符做了限定。

我现在实现的是编码之前过来的字符必须是UTF8编码,这样才能通过我自己实现的程序转化成unicode编码。

(2)上面的一切准备只是为我们组织PDU串:

1>初始化:ATZ\r

2>设置文本模式:AT+CMGF=0\r(0:pdu模式,1:text模式)

3>设置PDU头:

typedef struct {

23     char SCA[16];       // 短消息服务中心号码(SMSC地址)

24     char TPA[16];       // 目标号码或回复号码(TP-DA或TP-RA)

25     char TP_PID;        // 用户信息协议标识(TP-PID)

26     char TP_DCS;        // 用户信息编码方式(TP-DCS)

27     char TP_SCTS[16];   // 服务时间戳字符串(TP_SCTS), 接收时用到

28     char TP_UD[16];     // 原始用户信息

char index;        //短消息序号,在读取时用到

}SM_PARAM;

417     // SMSC地址信息段

418     memset(buf, 0, sizeof(buf));

419     nLength = strlen(pSrc->SCA);    // SMSC地址字符串的长度

420     buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1;    // SMSC地址信息长度

421     buf[1] = 0x91;                // 固定: 用国际格式号码

422     nDstLength = gsmBytes2String(buf, pDst, 2);        // 转换2个字节到目标PDU串

423     nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength);    // 转换SMSC到目标PDU串

424

425     // TPDU段基本参数、目标地址等

426     memset(buf, 0, sizeof(buf));

427     nLength = strlen(pSrc->TPA);    // TP-DA地址字符串的长度

428     buf[0] = 0x11;            // 是发送短信(TP-MTI=01),TP-VP用相对格式(TP-VPF=10)

429     buf[1] = 0;               // TP-MR=0

430     buf[2] = (char)nLength;   // 目标地址数字个数(TP-DA地址字符串真实长度)

431     buf[3] = 0x91;            // 固定: 用国际格式号码

432     nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4); // 转换4个字节到目标PDU串

433     nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 转换TP-DA到目标PDU串

434

435     // TPDU段协议标识、编码方式、用户信息等

436     //nLength = strlen(pSrc->TP_UD);    // 用户信息字符串的长度

437     memset(buf, 0, sizeof(buf));

438     buf[0] = pSrc->TP_PID;        // 协议标识(TP-PID)

439     buf[1] = pSrc->TP_DCS;        // 用户信息编码方式(TP-DCS)

440     buf[2] = 1;                   // 有效期(TP-VP)为5分钟

buf[3] = str2hex(user_pdu, pSrc->TP_UD); //用户信息的长度

465     nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4);        // 转换该段数据到目标PDU串

strcat(pdu, "\x01a");  //以CTRL-A结束

gsmString2Bytes(pdu, &nSmscLength, 2);    // 取PDU串中的SMSC信息长度

4>发送信息长度:AT+CMGS=长度,这步重要长度不对是发不出去的。

5>发送用户信息

如对PDU不怎么了解,网上有很多关于PDU资料,加上我这些应该很容易就可以实现发短信了。

阅读(10022) | 评论(1) | 转发(0) |

sms+cmgs+pdu+java_实现sms短信发送+pdu模式(支持中英文发送)相关推荐

  1. SMS短信的PDU编码规则

    先来看两张图: 1. 发送方PDU格式SMS-SUBMIT-PDU *1Message type (1 octet)                                           ...

  2. STM32使用GSM模块发送中英文短信(TEXT模式到PDU模式的转换)

    STM32使用GSM模块发送中英文短信(TEXT模式到PDU模式的转换) 目的是按下按键,短信发送 PDU转换网站 链接: PDU转换网站. 使用硬件: ··· 开发板:正点原子战舰V3 GSM模块: ...

  3. Java使用短信猫发信息(向串口发送AT指令)

    使用Java发送短信息的方式有两种: 1>使用第三方平台的http请求进行发送,优点是接口简单,使用方便,发送的效率高,多条可以同时发送,缺点是短信平台,三大运营商不提供接口,都是第三方平台,但 ...

  4. 安卓短信功能全解:调用系统短信功能发送短信、彩信,使用SmsManager发送短信,并监听发送短信的投递情况,使用广播接收器监听接收的短信。

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓短信功能全解:调用系统短信功能发送短信.彩信,使用SmsManager发送短信,并监听发送短信的投递情况,使用广播接收器监听接收的短信. 首先需要 ...

  5. php短信验证 免费_php如何实现发送短信验证码(图文)

    这篇文章分享给大家的内容是关于php发送短信验证码,内容很有参考价值,希望可以帮到有需要的小伙伴. 业务: 手机端点击发送验证码,请求发送到php端,由php调用第三方平台(我们使用的是榛子云短信ht ...

  6. python发送手机验证码_[python发送短信验证码不用三方模块]python发送短信验证码...

    业务: 手机端点击发送验证码,请求发送到python端,由python调用第三方平台(我们使用的是榛子云短信http://smsow.zhenzikj.com)的短信接口,生成验证码并发送. 代码: ...

  7. php手机号码一分钟发送一次短信_限制一分钟只能发送一次手机短信

    为什么要限制一分钟之内只能发送一次手机短信呢? 防止恶意攻击. 什么场景需要发送手机短信? (a)手机号注册 (b)通过手机找回密码 (c)手机号绑定,手机号换绑 (d)转账时手机号接收动态口令(一次 ...

  8. 阿里短信服务 php实例,阿里大鱼发送sms 短信 php demo示例

    最近项目中考虑使用阿里大鱼的sms短信发送服务,不过,在找到阿里大鱼php sdk的 时候,尼玛,问题来了! 我就想用个短信而已啊....竟然给我打包了好多 什么httpdns 什么kfcsearch ...

  9. 超级短信 handcent sms v4.4.1 android,超级短信Handcent SMS V

    超级短信Handcent SMS V3.2.9版 软件名称:超级短信Handcent SMS 推荐指数:☆☆☆☆ 系统支持:Android 1.5.1.6.2.0.2.1和2.2 超级短信Handce ...

最新文章

  1. android启动流程之lk,Android系统之LK启动流程分析(一)
  2. Delphi Excel操作,写了个ADODataSet转Excel的函数作为后期学习的例子
  3. Microsoft 数据访问组件 (MDAC) 的版本历史记录
  4. dp_c_区间dp_g
  5. solidity智能合约[37]-以太坊虚拟机数据存储
  6. monggodb和MySQL同步问题_monggoDB添加到windows服务
  7. 天呢,小学生都在B站讲算法?
  8. ZPL效果在线打印测试和相关手册及编程语言资料
  9. jTopo 功能完善
  10. Hive应用:选取分隔符
  11. airtest上的滑动操作swipe
  12. Chrome浏览器截取网页生成图片
  13. 小辩五笔输入法的高效及拼音输入法的盲目夸大--评所谓整句输入技术
  14. jasypt对yml文件中密码加密
  15. 2017年四月份小结和五月份计划
  16. C语言编写规范之注释
  17. Windows10发布会九大不可错过的看点
  18. GBase 8m的高可用性详解
  19. java怎么算数_JAVA初学者——算数运算符
  20. shell魔幻盒子_嵌入式操作系统实训报告——魔幻盒子

热门文章

  1. php疫情上报管理系统 毕业设计-附源码170948
  2. 2015-2020年智慧城市物联网市场CAGR将高达23.2%
  3. 文件夹图标后缀名变成.ink的解决办法
  4. 战神引擎获取版本信息失败_传奇手游架设教程:战神引擎更新到100%卡住怎么办?解决办法分享...
  5. 如何使用 Creator【摄像机组件】实现局部缩放的效果?
  6. 《秘密》卷一:秘密-秘密的发现
  7. mysql数据刷盘过程详解_MySQL延迟问题和数据刷盘策略流程分析
  8. 【录用案例】1区SCI仅1个月14天录用,新增19篇录用、5篇见刊、6篇检索
  9. 超微主板重置IPMI密码 Windows系统
  10. 【vue 语音播报(文字转语音)】