這款簡訊發送軟體的模式是通過電腦的串口聯結一台簡訊modem(這裡我用的是西門子6688手機),通過發送軟體去控制簡訊modem來傳送簡訊。
既然需要通過串口來與簡訊modem進行通訊,就需要一個串口通訊控制項,這裡我使用了微軟的mscomm32.ocx串口通訊控制項。具體實現方法是通過對mscomm32.ocx的幾個屬性設定(串口連接埠設定、發送資料類型設定、讀寫緩衝區設定等)來達到串口與簡訊modem進行通訊的目的,然後對輸入的簡訊息進行編碼,把編碼後的簡訊息發送至簡訊modem,再通過AT指令去控制modem的發送。整個軟體由三個程式組成,一是發送主程式,二是簡訊編碼程式,三是串口通訊控制項,下面作一一介紹。
一、串口通訊控制項
微軟的串列通訊控制項MSCOMM簡化了編程,可以快速的建立通訊應用程式。MSComm 控制項通過序列埠傳輸和接收資料,為應用程式提供串列通訊功能。MSComm控制項在串口編程時非常方便,程式員不必去花時間去瞭解較為複雜的API函數。
MSCOMM的屬性和事件
MSComm 控制項有很多重要的屬性,這裡只講本程式應用的幾個屬性。
1)CommPort:設定並返回通訊連接埠號碼,在設計時,可以設定成從 1 到 16 的任何數,必須在開啟連接埠之前設定 CommPort 屬性;
2)Settings: 以字串的形式設定並返回傳輸速率、同位、資料位元、停止位,設定的格式為“BBBB,P,D,S”,BBBB 為傳輸速率,P 為同位,D 為資料位元數,S 為停止位元;
3)PortOpen: 設定並返回通訊連接埠的狀態。也可以開啟和關閉連接埠,true表示串口開啟;
4)Input: 從接收緩衝區返回和刪除字元;
5)Output: 向傳輸緩衝區寫一個字串;
6)InputMode:設定發送和接收資料的類型,InputModeConstants.comInputModeText表示文本的方式,InputModeConstants.comInputModeBinary表示二進位的方式;
7)InputLen:讀取接收緩衝區的位元組數,如果為0則表示讀取整個緩衝區的資料
8)OutBufferCount:返回傳送緩衝區內等待發送的位元組數,可通過設定該屬性為0來清空緩衝區。
9)InBufferCount:返回接收緩衝區內等待發送的位元組數,可通過設定該屬性為0來清空緩衝區。
二、簡訊的編碼
簡訊息是文本資訊,簡訊modem只支援ASCII格式碼的文本資訊,ASCII碼格式包括英文字母A-Z和數字0-9及一些標點符號等字元,為此對於中文簡訊息必須通過編碼使中文變成ASCII碼,簡訊編碼有三種模式:BLOCK MODE、基於AT指令的TEXT MODE和基於AT指令的PDU MODE的編碼,西門子6688手機支援PDU MODE的編碼,這種編碼方式是把簡訊本文經過16進位編碼後發送。PDU的編碼又分為7bit編碼、8bit編碼和16bit編碼,7bit編碼最多可發送160個字元,8bit編碼最多可發送140個字元,而16bit編碼最多可發送70個字元,這種編碼被用顯示Unicode(UCS2)文體資訊,可被大多數手機顯示,所以這裡我採用的是UCS2編碼,其最多可發送70個字元,不管是英文還是中文。
一條簡訊由三部分組成,一是接收方的手機號碼,二是簡訊中心號碼,三是簡訊內容。在實際的編碼過程中,這三部分是分開來進行的,最後再把它們合三為一。
⑴、簡訊中心號碼編碼
首先把簡訊中心號碼的奇數位與偶數位互換,然後看其長度是否為偶數,如果不是,在最後添加F,並對最後一位與F互換位置。接著在號碼前加上91,相當於加上一個"+"字元。最後計算編碼後的總長度併除以2,並把這個數格式化為二位的16進位數。例如:廣州的簡訊中心號碼為8613800200500,編碼後為0891683108200005F0,08是91683108200005F0的長度除2,即16/2=8,二位16進位表示就是08。
㈡、接收方手機號碼編碼
首先檢查當前接收方手機號碼的前兩位是否有86字樣,如果沒有就補上86,然後奇偶位互換,最後檢查整個長度是否為偶數,如果不是就加上F,並對最後一位與F互換位置,如手機號碼為13918765434,編碼後為683119785634F4。
㈢、簡訊內容編碼
首先採用Big-Endian位元組順序的Unicode格式編碼,即高低位互換,接著把它存入一個位元組數組,然後去掉進行Unicode編碼過程中的“-”字元,最後把整條編碼好後的簡訊內容長度除2,並格式化成二位16進位數添加到編碼後的簡訊內容前面。
例如,簡訊內容為:你好,HELLO!,編碼後為:4F60597DFFOC00480065006C006C006F0021,最後根據國內PDU編碼的原則在接收手機號編碼前加上11000D91,在簡訊內容前加上000800,並把以上三部分編碼串起來即可。
三、AT指令
AT指令類似於DOS命令,由命令與一些參數組成,來完成對modem實現某一功能的控制。AT指令有很多個,它的基本格式是AT+操作功能符+斷行符號,我編寫的這款簡訊發送軟體實際只使用了兩個AT指令,分別是:AT+CSCA?和AT+CMGS,前一個是擷取存於手機SIM卡裡面的簡訊中心號碼的命令,後面一個是發送一條簡訊命令。通常向modem發送一個AT指令,modem如果執行完成都會有一個執行結果回送。
四、簡訊發送軟體主程式
下面是主程式的代碼,圖1是主程式的運行介面
PDUdecoding sms = new PDUdecoding();
MSComm com=new MSComm();
Thread t ,w;
private
{
xiancheng1();
}
void xiancheng1()//串連串口
{
t= new Thread(new ThreadStart(InitCom));//定義連接線程
t.Start();//啟動線程
}
private bool lianjie(string duankou,string botelv)
{
try
{
string dk=duankou.Trim().Substring(3);
if (com.PortOpen==true)com.PortOpen=false;
com.CommPort = Convert.ToInt16(dk);//串口號
com.InputMode =MSCommLib.InputModeConstants.comInputModeText;//傳輸的資料形式是文本
com.InputLen=0;//讀取整個接收緩衝區內容
com.Settings = botelv+",N,8,1"; //串口基本參數設定
com.PortOpen=true;//開啟串口
com.OutBufferCount=0;//清空發送緩衝區
com.InBufferCount=0;//清空接收緩衝區
return true;
}
catch
{
MessageBox.Show("錯誤:串連參數有錯,請重新選擇!");
return false;
}
}
void InitCom()
{
int i;
if(lianjie(duankou.SelectedItem.ToString(),bote.SelectedItem.ToString()))
string Buffer="";
string bufy="AT+CSCA?\r";
for(i=0;i<5;i++)
com.Output = bufy; //發送資料到串口發送緩衝區
Buffer+=com.Input;//接收串口接收緩衝區的資料
break;
}
}
if(i>4)
{
label5.Text="串連失敗,重新串連!!";
}
else
{
int Num1=Buffer.LastIndexOf("86");
zhongxinhao.Text =Buffer.Substring(Num1,13);
label5.Text="串連成功!!";
}
}
else
{
label5.Text="串連失敗,重新串連!!";
}
com.PortOpen=false;
t.Abort();
}
private void button2_Click(object sender, System.EventArgs e)
{
if (com.PortOpen==true)com.PortOpen=false;
Application.Exit();
}
void fsduanxin()
{
w= new Thread(new ThreadStart(fs));//定義發送線程
w.Start();//啟動線程
}
private void button3_Click(object sender, System.EventArgs e)
{
fsduanxin();
}
void fs()
{
if(lianjie(duankou.SelectedItem.ToString(),bote.SelectedItem.ToString()))
{
string dhnum=shoujihaoma.Text;
fsdx(dhnum);//傳送簡訊
com.PortOpen=false;
w.Abort();
}
}
void fsdx(string danhuahaoma)//傳送簡訊程式段
{
int i=0;
duanxinshoufa.Text="正在發送,稍候";
string Buffer="";
string decodedSMS = sms.smsDecodedsms(zhongxinhao.Text,danhuahaoma,neirong.Text);
string bufy="AT+CMGS="+sms.nLength+"\r";
for(i=0;i<10;i++)
{
com.Output = bufy;
Thread.Sleep(300);
Buffer+=com.Input;
Thread.Sleep(500);
if( Buffer.Length > 0 && Buffer.EndsWith("> "))//判斷AT指令執行的回送結果
{
string buf=decodedSMS+"\x01a";
com.Output = buf;
Thread.Sleep(1000);
string chenggong = "發送成功!";
string Result = String.Format("{0},{1},{2}。\n",danhuahaoma,neirong.Text,chenggong);
duanxinshoufa.Text += "\r\n"+Result;
break;
}
duanxinshoufa.Text +=".";
}
if(i>9)
{
duanxinshoufa.Text ="發送失敗,請重新發送!";
w.Abort();
}
}
在程式中使用了線程式控制制,目的是協調程式運行與串口通訊之間的同步問題。另外在主程式中使用AT指令時都使用了迴圈,通過對AT指令執行結果回送的檢測,判斷AT指令是否被正確地執行,如果未被正確執行,則通過迴圈控制重發AT指令直至AT指令正確執行為止。
此程式介面簡單易用,我把他放上來給有興趣的朋友使用(點擊這裡下載)。使用此程式的注意事項:
1、此程式我只在西門子6688,SL45i手機上成功應用。
2、此程式是在.NET平台上開發的,所以要在你的電腦上安裝ms.net.framework1.1,這是一個免費軟體,網上有下載。
3、程式中所使用的mscomm32.ocx控制項需要註冊,註冊步驟如下:
①、將Mscomm32.ocx,Mscomm32.dep兩個檔案複製到系統SYSTEM32檔案夾中。
②、用Windows下的註冊工具regsvr32註冊該OCX控制項,點擊“開始”->"運行",再在其中填入 Regsvr32 C:\windows\system32\Mscomm32.ocx。
③、在註冊表中手工建立一個主鍵項:先在點擊“開始”->"運行",再在其中填入regedit命令開啟註冊表,找到HKEY_CLASSES_ROOT\Licenses,在其中添加主鍵:4250E830-6AC2-11cf-8ADB-00AA00C00905 並將內容設定為:kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun。
{
if(Buffer.IndexOf("86")!=-1)//判斷AT指令執行的回送結果
Thread.Sleep(1000); {{
void button1_Click(object sender, System.EventArgs e)