一、 原理与规定
1、 原理:
SMS是由Esti 所制定的一个规范(GSM 03.40 和 GSM 03.38)。收发消息的模式有:文本模式或者PDU(protocol description unit)模式。文本模式只能发送普通的ASCII字符,而要发送图片、铃声、其它编码的字符(如中文)就必须采用PDU模式。PDU模式中,可以采用三种编码方式来编码要发送的内容,分别是 7-bit编码、8-bit编码、16-bit编码。7-bit编码用于发送普通的ASCII字符;8-bit编码通常用于发送数据消息,比如图片和铃声 等;而16-bit编码用于发送Unicode字符。在这三种编码方式下,可以发送的最大字符数分别是 160、 140、 70。7-bit编码与ASCII并不是完全对应的,但对于普通大小写英文字母和标点符号的部分,两者是相同。
使用Windows CE可以发送PDU模式的SMS,这里主要讨论使用SmsSendMessage函数发送7-bit编码和16-bit编码的短消息时应使用的参数及各种情况的测试。
2、 规定:
下面是使用的完整代码,其中红色加粗的部分是在后面的测试中会改为使用其它参数,代码其它部分则保持不变。
SMS_HANDLE smsHandle;
HRESULT hr = SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smsHandle, NULL);
ASSERT(hr == ERROR_SUCCESS);//简化代码,未使用错误处理
TEXT_PROVIDER_SPECIFIC_DATA tpsd;
tpsd.dwMessageOptions = PS_MESSAGE_OPTION_STATUSREPORT;//需要状态报告
tpsd.psMessageClass = PS_MESSAGE_CLASS1;
tpsd.psReplaceOption = PSRO_NONE;
//psMessageClass有四种参数PS_MESSAGE_CLASS0到PS_MESSAGE_CLASS3,一般只使用PS_MESSAGE_CLASS0或PS_MESSAGE_CLASS1。PS_MESSAGE_CLASS0表示短信在被接收后立即显示且不存储在收件箱(称为闪信) ,PS_MESSAGE_CLASS1表示一般的情况,被接收后存储到收件箱并发送一个确认回短信中心,发送方收到一个已被接收的状态报告。
SMS_ADDRESS smsaDestination;
smsaDestination.smsatAddressType = SMSAT_INTERNATIONAL;
lstrcpy(smsaDestination.ptsAddress, _T("8613588881696"));//目的号码,也可以写成+8613588881696的形式
//以下szMessage在后面的测试中会改为使用其它参数
TCHAR szMessage[] = _T("adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfdf70adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfd140adsfdsdfdadssfdsa160");
DWORD length = lstrlen(szMessage) * sizeof (TCHAR);//szMessage的字节长度
//以下encode在后面的测试中会改为使用其它参数
SMS_DATA_ENCODING encode = SMSDE_GSM;
/*SMS_DATA_ENCODING枚举有3个值,SMSDE_OPTIMAL表示由短信中心决定字符的格式,SMSDE_GSM使用7-bit编码,SMSDE_UCS2使用16-bit (Unicode)编码*/
hr = SmsSendMessage(smsHandle, NULL, &smsaDestination, NULL,
(PBYTE) szMessage, length,
(PBYTE) &tpsd, 12, encode,
SMS_OPTION_DELIVERY_NONE, NULL);
//倒数第4个参数是tpsd的长度,这里只能使用12,如果使用sizeof(tpsd)则无法成功发送短消息,因为发送短消息时TEXT_PROVIDER_SPECIFIC_DATA只有前三个结构有用,长度也只能指定为前三个结构的总长度12
SmsClose (smsHandle);
ASSERT(hr == ERROR_SUCCESS);
二、 测试及结论
发送的短消息全为ASCII字符
1. 发送的短消息全部为ASCII字符,且字符个数少于160个的情况(字符个数为lstrlen(szMessage))
TCHAR szMessage[] = _T("adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfdf70adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfd140adsfdsdfdadssfd158");//158个字符
SMS_DATA_ENCODING encode = SMSDE_GSM;//也可以使用encode = SMSDE_OPTIMAL;
结果:收到短消息1条,第1条长158
结论:发送短消息全部为ASCII字符,且字符个数少于160个时,系统会按一条短消息发送。这时SMS_DATA_ENCODING参数选择SMSDE_GSM或SMSDE_OPTIMAL都可以。
2. 发送的短消息全部为ASCII字符,且字符个数等于160个的情况
TCHAR szMessage[] = _T("adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfdf70adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfd140adsfdsdfdadfdssfd160");//160个字符
SMS_DATA_ENCODING encode = SMSDE_GSM;//也可以使用encode = SMSDE_OPTIMAL;
结果:收到短消息1条,第1条长160
结论:发送短消息全部为ASCII字符,且字符个数等于160个时,系统会按一条短消息发送。这时SMS_DATA_ENCODING参数选择SMSDE_GSM或SMSDE_OPTIMAL都可以。
3. 发送的短消息全部为ASCII字符,且字符个数超过160个的情况
TCHAR szMessage[] = _T("adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfdf70adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfd140adsfdsdfdadssfdsa1601234567");//167个字符
SMS_DATA_ENCODING encode = SMSDE_GSM;//也可以使用encode = SMSDE_OPTIMAL;
结果:收到短消息2条,第1条长153,第2条长14
结论:1)发送短消息全部为ASCII字符,且字符个数超过160个时,系统会自动将短消息进行分割,但并不是按每条160进行分割,而是按每条153。
2)发送短消息全部为ASCII字符,SMS_DATA_ENCODING参数选择SMSDE_GSM或SMSDE_OPTIMAL都可以。
4. 发送的短消息不全为ASCII字符,且字符个数少于或等于70个的情况
TCHAR szMessage[] = _T("adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfdf70adfadsfasdgasryoufqrelfjbhldasfasdyrfasdfasdfasoerqljjdasfdasfasdfd140adsfdsdfdadssfdsa1601234567");//167个字符
SMS_DATA_ENCODING encode = SMSDE_GSM;//也可以使用encode = SMSDE_OPTIMAL;
结果:收到短消息2条,第1条长153,第2条长14
结论:1)发送短消息全部为ASCII字符,且字符个数超过160个时,系统会自动将短消息进行分割,但并不是按每条160进行分割,而是按每条153。
2)发送短消息全部为ASCII字符,SMS_DATA_ENCODING参数选择SMSDE_GSM或SMSDE_OPTIMAL都可以。
发送的短消息不全为ASCII字符
5. 发送的短消息不全为ASCII字符,且字符个数少于70个的情况(以下字符个数的计算方式为lstrlen(szMessage),注意不是lstrlen(szMessage) * sizeof (TCHAR))
TCHAR szMessage[] = _T("二零零八adfadsfdasfekutkadfyqierbhzteqwrgadgffsfgsdfgcvadgfddfafdafa68");//68个字符
SMS_DATA_ENCODING encode = SMSDE_GSM;//也可以使用encode = SMSDE_OPTIMAL;
结果:收到短消息1条,第1条长68
结论:发送短消息全部为ASCII字符,且字符个数少于160个时,系统会按一条短消息发送。这时SMS_DATA_ENCODING参数选择SMSDE_GSM或SMSDE_OPTIMAL都可以。
6. 发送的短消息不全为ASCII字符,且字符个数超过70个的情况
TCHAR szMessage[] = _T("二零零八adfadsfdasfekutkadfyqierbhzteqwrgadgffsfgsdfgcvadgfddfaaddfaddfasfdafa76");//76个字符
SMS_DATA_ENCODING encode = SMSDE_UCS2;//也可以使用encode = SMSDE_OPTIMAL;
结果:收到短消息2条,第1条长67,第2条长9
结论:1)发送短消息不全为ASCII字符,且字符个数超过70个时,系统会自动将短消息进行分割,但并不是按每条70进行分割,而是按每条67。
2)发送短消息不全为ASCII字符,SMS_DATA_ENCODING参数选择SMSDE_UCS2或SMSDE_OPTIMAL都可以。
总结
1、使用Windows CE的SMS API函数SmsSendMessage可以发送7-bit编码和16-bit编码的短消息(未测试8-bit编码)。单条短消息的最大字符数分别是160和70。发送短消息全部为ASCII字符,SMS_DATA_ENCODING参数选择SMSDE_GSM或SMSDE_OPTIMAL都可以。发送短消息不全为ASCII字符,SMS_DATA_ENCODING参数选择SMSDE_UCS2或SMSDE_OPTIMAL都可以。建议选择SMSDE_OPTIMAL。
2、发送短消息全部为ASCII字符,且字符个数超过160个时,系统会自动将短消息进行分割,但并不是按每条160进行分割,而是按每条153。发送短消息不全为ASCII字符,且字符个数超过70个时,系统会自动将短消息进行分割,但并不是按每条70进行分割,而是按每条67。
3、根据以上总结1和总结2,发送短消息的字符数超过160或70时,应该自行进行分割,而不应交由系统进行分割,这样可以最大限度的利用单条短消息的最大字符数分别是160和70的条件。关于判断是否全为ASCII字符及超过160或70时自行进行分割的办法就很简单了,网上也有很多相关资料,代码就不再给出了。