1. 程式人生 > >C++ 發手機簡訊(很易很簡單)

C++ 發手機簡訊(很易很簡單)

由於市場需求,飛鴿傳書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;
}