由于市场需求,飞鸽传书C/S版XEIM需要集成短信发送功能,于是进行了一番苦而累的研究,今天总算有点点成果,故来自己的网站晒晒,只是点点成果,非常有限,还希望高人能够指点一下。
本文欢迎大家转载,但请注明出处:http://www.freeeim.com/另外,由于短信群发会造成各种各样的问题,有些是违法的,希望大家别以身试法。开始吧!实现短信发送,必须有发送短信的设备,我用的是GSM MODEM,设备没什么特别,通电接上电脑就行了,没驱动,没设置。所有问题都在 C++ 编程上,因为设备是COM接口,所以涉及到一些COM I/O 操作,不过非常简单,因为WINDOWS 的所有I/O 都可以用File I/O API 来完成,也就是OpenFile、WriteFile、ReadFile这几个函数啦,简单吧!第一步:发送Hello world!到你手机
先别急着写代码,我们用现有的工具(超级终端)吧。启动方法【开始】->【所有程序】->【附件】->【通讯】->【超级终端】(别怪我罗嗦,我第一次真的不知道‘超级终端’在哪里),启动后在‘连接描述’对话框的‘名称’里就随便填‘aa’就行了,没意义但必填而已,接着会出现‘连接到’对话框,这里需选一下,在‘连接时使用’选‘COM1’,因为我的 GSM MODEM 是连接在COM1的,要是你的有变动的话,可以尝试选其他,例如‘COM2’,最后按确定,出现‘COM1属性’对话框,按这个参数设置吧:每秒位数[9600],数据位[8],奇偶校验[无],停止位[1],数据流控制[无]。点确定,配置完毕,然后在超级终端的输入框输入‘AT’,如果有显示‘OK’的话,那么你成功了,GSM MODEM 与电脑连接正常。
输入以下指令来发送短信吧:AT+CMGF=1
// 成功的话会返回‘OK’
AT+CMGS=137888888XX
成功的话会返回‘>’这个大于号,注意,手机号当然要填你自己的啦。
> Hello world!
// 输完Hello world!后,你按住CTRL 然后按 Z 字母键,这是古久以前 DOS 的 EOF 标志。
// 顺利的话,你的手机3秒内会收到短信。
如果你这里没成功,没关系,上GOOGLE或BAIDU找找“超级终端 AT指令之类的”就行了。第二步:开始C++编程
这里需要了解“短信PDU编码解码”这个问题,可以上GOOGLE 或BAIDU查查,如果我在这里说的话,文章就会太长了,其实这问题很简单,而且我会把处理代码给出来。PDU编码函数:LPSTR CXSMSDlg::ChangeCODE(LPCTSTR lpText)
{
 DWORD dwMinSize;
 dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpText, -1, NULL, 0); WCHAR *tmp = new WCHAR[dwMinSize];
 // Convert headers from ASCII to Unicode.
 MultiByteToWideChar (CP_ACP, 0, lpText, -1, tmp, dwMinSize); char *newTmp = new char[dwMinSize*4];
 memset(newTmp, 0, (dwMinSize-1)*4); for(DWORD i=0; i<dwMinSize-1; i++)
 {
  char buf[5];
  sprintf(buf, "%04X", tmp[i]);
  strcat(newTmp, buf);
 } return newTmp;
}// 设置短信中心
LPSTR SMS_Center_CODE(LPCTSTR lpText)
{
 char *tmp = new char[20];
 tmp[0] = '9';
 tmp[1] = '1';
 tmp[2] = '6';
 tmp[3] = '8';
 for (int i=0; i<6; i++)
 {
  tmp[i*2+4] = lpText[i*2+1];
  tmp[i*2+5] = lpText[i*2];
 }
 tmp[14] = 'F';
 tmp[16] = NULL;
 int len = strlen(tmp);
 char szLen[3];
 sprintf(szLen, "%02d", len/2);
 for(i=0; i<18; i++)
 {
  tmp[19-i] = tmp[17-i];
 }
 tmp[0] = szLen[0];
 tmp[1] = szLen[1]; return tmp;
}// 手机号码的编码
LPSTR SMS_Phone(LPCTSTR lpText)
{
 char *tmp = new char[15];
 tmp[0] = '6';
 tmp[1] = '8';
 for (int i=0; i<6; i++)
 {
  tmp[i*2+2] = lpText[i*2+1];
  tmp[i*2+3] = lpText[i*2];
 }
 tmp[12] = 'F';
 tmp[14] = NULL; char *ret = new char[20+8+6];
 sprintf(ret, "%s%s%s", "11000D91", tmp, "000800");
 delete [] tmp; return ret;
}// 提交短信
void SendSMS()
{
 char *pmsg =pData; //ChangeCODE(pData);
 char *pnum = SMS_Phone(strTmp);
 CString sendText;
 int nLen = (strlen(pnum)+strlen(pmsg)) / 2;
 CString strbbs;
 strbbs.Format("Num Len:%d -- Msg Len%d", strlen(pnum), strlen(pmsg));
 sendText.Format("AT+CMGS=%d %s%s%sa",
   nLen, SMS_Center_CODE(m_strSMSCenter),
   pnum, pmsg); CString bbbb;
 bbbb.Format("PDU:%d--TP-UL:%d", nLen, strlen(pmsg));
 delete [] pnum;
}注明出处:http://www.freeeim.com/

解决方案 »

  1.   

    楼主最好讲的分开一些层次,AT指令发短信主要由AT指令 + 短信编码两部分组成。你的程序都写好了,全是将参数转成短信编码的,就差说出来了。
      

  2.   

    就是控制GSM Modem发短信而已,不算很难,手机卡是要放在modem里的吧,收短信楼主有做过么??
      

  3.   

    UP
    学习下PDU格式编码的处理
      

  4.   

    通过网上的转换算法,转成16bit的linear PCM编码wav文件
      

  5.   

    是否需要看GSM相关的规范呢?