最近在工作中遇到一个比较怪异的现象,在某些省区与SP的短信交互存在问题,短信发送不出去。查了一下原因:SmsSendMessage参数设置的问题。
在Windows Mobile 5.0SDK的HelloSMS例子中,发送短信的代码是这样写的
 void SendSMS(BOOL bSendConfirmation, BOOL bUseDefaultSMSC, LPCTSTR lpszSMSC, LPCTSTR lpszRecipient, LPCTSTR lpszMessage)
void SendSMS(BOOL bSendConfirmation, BOOL bUseDefaultSMSC, LPCTSTR lpszSMSC, LPCTSTR lpszRecipient, LPCTSTR lpszMessage)


 {
{
 SMS_HANDLE smshHandle;
    SMS_HANDLE smshHandle;
 SMS_ADDRESS smsaSource;
    SMS_ADDRESS smsaSource;
 SMS_ADDRESS smsaDestination;
    SMS_ADDRESS smsaDestination;
 TEXT_PROVIDER_SPECIFIC_DATA tpsd;
    TEXT_PROVIDER_SPECIFIC_DATA tpsd;
 SMS_MESSAGE_ID smsmidMessageID;
    SMS_MESSAGE_ID smsmidMessageID;

 // try to open an SMS Handle
    // try to open an SMS Handle
 if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))
    if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))

 
     {
{
 MessageBox(NULL,
        MessageBox(NULL,
 (LPCTSTR)LoadString(ghInstance, IDS_ERROR_SMSOPEN, 0, 0),
                    (LPCTSTR)LoadString(ghInstance, IDS_ERROR_SMSOPEN, 0, 0), 
 (LPCTSTR)LoadString(ghInstance, IDS_CAPTION_ERROR, 0, 0),
                    (LPCTSTR)LoadString(ghInstance, IDS_CAPTION_ERROR, 0, 0),
 MB_OK | MB_ICONERROR);
                    MB_OK | MB_ICONERROR);
 return;
        return;
 }
    }

 // Create the source address
    // Create the source address
 if(!bUseDefaultSMSC)
    if(!bUseDefaultSMSC)

 
     {
{
 smsaSource.smsatAddressType = SMSAT_INTERNATIONAL;
        smsaSource.smsatAddressType = SMSAT_INTERNATIONAL;
 _tcsncpy(smsaSource.ptsAddress, lpszSMSC, SMS_MAX_ADDRESS_LENGTH);
        _tcsncpy(smsaSource.ptsAddress, lpszSMSC, SMS_MAX_ADDRESS_LENGTH);
 }
    }

 // Create the destination address
    // Create the destination address
 smsaDestination.smsatAddressType = SMSAT_INTERNATIONAL;
    smsaDestination.smsatAddressType = SMSAT_INTERNATIONAL;
 _tcsncpy(smsaDestination.ptsAddress, lpszRecipient, SMS_MAX_ADDRESS_LENGTH);
    _tcsncpy(smsaDestination.ptsAddress, lpszRecipient, SMS_MAX_ADDRESS_LENGTH);

 // Set up provider specific data
    // Set up provider specific data
 memset(&tpsd, 0, sizeof(tpsd));
    memset(&tpsd, 0, sizeof(tpsd));
 tpsd.dwMessageOptions = bSendConfirmation ? PS_MESSAGE_OPTION_STATUSREPORT : PS_MESSAGE_OPTION_NONE;
    tpsd.dwMessageOptions = bSendConfirmation ? PS_MESSAGE_OPTION_STATUSREPORT : PS_MESSAGE_OPTION_NONE;
 tpsd.psMessageClass = PS_MESSAGE_CLASS1;
    tpsd.psMessageClass = PS_MESSAGE_CLASS1;
 tpsd.psReplaceOption = PSRO_NONE;
    tpsd.psReplaceOption = PSRO_NONE;
 tpsd.dwHeaderDataSize = 0;
    tpsd.dwHeaderDataSize = 0;

 // Send the message, indicating success or failure
    // Send the message, indicating success or failure
 if(SUCCEEDED(SmsSendMessage(smshHandle, ((bUseDefaultSMSC) ? NULL : &smsaSource),
    if(SUCCEEDED(SmsSendMessage(smshHandle, ((bUseDefaultSMSC) ? NULL : &smsaSource), 
 &smsaDestination, NULL, (PBYTE) lpszMessage,
                                 &smsaDestination, NULL, (PBYTE) lpszMessage, 
 _tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd,
                                 _tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd, 
 sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_OPTIMAL,
                                 sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_OPTIMAL, 
 SMS_OPTION_DELIVERY_NONE, &smsmidMessageID)))
                                 SMS_OPTION_DELIVERY_NONE, &smsmidMessageID)))

 
     {
{
 MessageBox(NULL,
        MessageBox(NULL,
 (LPCTSTR)LoadString(ghInstance, IDS_SMSSENT, 0, 0),
                    (LPCTSTR)LoadString(ghInstance, IDS_SMSSENT, 0, 0), 
 (LPCTSTR)LoadString(ghInstance, IDS_CAPTION_SUCCESS, 0, 0),
                    (LPCTSTR)LoadString(ghInstance, IDS_CAPTION_SUCCESS, 0, 0),
 MB_OK);
                    MB_OK);
 }
    }
 else
    else

 
     {
{
 MessageBox(NULL,
        MessageBox(NULL,
 (LPCTSTR)LoadString(ghInstance, IDS_ERROR_SMSSEND, 0, 0),
                    (LPCTSTR)LoadString(ghInstance, IDS_ERROR_SMSSEND, 0, 0), 
 (LPCTSTR)LoadString(ghInstance, IDS_CAPTION_ERROR, 0, 0),
                    (LPCTSTR)LoadString(ghInstance, IDS_CAPTION_ERROR, 0, 0),
 MB_OK | MB_ICONERROR);
                    MB_OK | MB_ICONERROR);
 }
    }

 // clean up
    // clean up
 VERIFY(SUCCEEDED(SmsClose(smshHandle)));
    VERIFY(SUCCEEDED(SmsClose(smshHandle)));
 }
}

这段代码在一般情况下是运行正确的,对于手机与手机的发送是不存在问题的,但是与SP的交互在某些省区就存在短信发送不出去的情况。
为了更好的理解这段代码,我们先来熟悉一下SmsSendMessage及各个参数。
SmsSendMessage
功能:Use the SmsSendMessage function to create and send an Short Message Service (SMS) message.(创建和发送短信,但短信发送后并不保存到发件箱中)
原型:
HRESULT SmsSendMessage (
const SMS_HANDLE smshHandle, // 调用SmsOpen时获得的短信句柄
const SMS_ADDRESS * const psmsaSMSCAddress, //指向短信中心号码的地址
const SMS_ADDRESS * const psmsaDestinationAddress, // 发送的目的地址
const SYSTEMTIME * const pstValidityPeriod, // 发送时间的有效期
const BYTE * const pbData, // 信息的内容部分
const DWORD dwDataSize,// 信息内容的长度
const BYTE * const pbProviderSpecificData, //运营商的附加数据
const DWORD dwProviderSpecificDataSize, // 附加数据的长度
const SMS_DATA_ENCODING smsdeDataEncoding, // 短信编码
const DWORD dwOptions, // 其他选项
SMS_MESSAGE_ID * psmsmidMessageID); // 用于得到系统回执的信息
(具体介绍可查看http://msdn.microsoft.com/en-us/library/aa455068.aspx)
在实际应用中短信发送不出去,但是SmsSendMessage的返回值是S_OK值。在一些文章中有人这样认为是短信编码的问题造成的。
如果编码格式不对可能造成短信中心网关把短信给吞掉的情况,程序虽然调用成功,但是就是目标号码收不到短信。函数参数中的后三个参数可以不用或设默认值都可以。
起初我也是认为这个地方造成的,很是兴奋。短信的回复内容恰为字母,我误以为短信内容此时是7-BIT的短消息,短信网关把短信给吞掉了,造成目标号码收不到短信。在练习中却也阴差阳错的成功了。很高兴的把理由归到了这个地方。并这样总结:SmsSendMessage可以支持7-bit的ASCII码的短消息,也支持16-bit的unicode的短消息。但内容为ASCII的时候,短信编码为 SMSDE_GSM或SMSDE_OPTIMAL,当内容不全是ASCII的时候,短信编码为SMSDE_GSM或SMSDE_OPTIMAL。所以回复内容改为汉字即可。
但是这样对么?起初我认为我的解释很合理.但是我却发现我的一个参数与原来的程序不一样.
是我在尝试中无意修改了一个参数,将
tpsd.psMessageClass = PS_MESSAGE_CLASS1;
修改为了
tpsd.psMessageClass = PS_MESSAGE_CLASSUNSPECIFIED;
这是发送短信中的运营商的指定数据TEXT_PROVIDER_SPECIFIC_DATA,它的参数psMessageClass是指
Text Short Message Service (SMS) messages with the appropriate flag can replace previously received notifications with a similar flag and originating address.
它有以下五个值:
PS_MESSAGE_CLASS0: The message should be displayed immediately but not stored. The MS shall send an acknowledgement to the service center when the message has successfully reached the MS. (被接受后立即显示但不存储(称为闪信)。需要向SMSC发送确认信息。)
PS_MESSAGE_CLASS1:The message should be stored and an acknowledgement should be sent to the Service Center when it is stored.(接收后被存储,一旦存储,需要向SMSC发送确认信息。)
PS_MESSAGE_CLASS2:The message should be transferred to the SMS data field in the subscriber identity module (SIM) before an acknowledgement is sent to the Service Center. 
PS_MESSAGE_CLASS3:When the message has successfully reached the destination and can be stored, an acknowledgement is sent to the Service Center.
PS_MESSAGE_CLASSUNSPECIFIED:The message Class is not set in the outgoing or incoming message. (对发出或收到的短信不进行设置)
 
分析以上五个值,前四个值有一个共同的特点,都需要向SMSC发送确认。而最后一个值没有设定。
这个值的改动,解决了我所遇到的问题。但究其原因,我有些想不通为什么?
    但是在实际应用中,出现了tmail.exe的异常。不知道是这个值的变动带来的问题,还是实际模块中存在的问题。还需要继续研究一下。
如果大家有知道的,给些建议哈.
	posted on 2009-03-10 14:14 
Sandy 阅读(6844) 
评论(13)  编辑 收藏 引用  所属分类: 
windows学习