四、 具體的內(nèi)部編程思路:
GPRS控件的編寫(xiě),我們用到的是Winsock控件,所以首先要先了解一下Winsock控件的使用。
1、Winsock控件的使用:
Winsock控件對(duì)用戶來(lái)說(shuō)是不可見(jiàn)的,我們?cè)诰帉?xiě)客戶端或服務(wù)器程序時(shí),通過(guò)設(shè)置控件的屬性并調(diào)用其方法即可實(shí)現(xiàn)數(shù)據(jù)的雙向交換。
如果創(chuàng)建客戶應(yīng)用程序,就必須知道服務(wù)器計(jì)算機(jī)名或者 IP 地址(RemoteHost 屬性),還要知道進(jìn)行“偵聽(tīng)”的端口(RemotePort 屬性),然后調(diào)用 Connect 方法。
如果創(chuàng)建服務(wù)器應(yīng)用程序,就應(yīng)設(shè)置一個(gè)收聽(tīng)端口(LocalPort 屬性)并調(diào)用 Listen 方法。當(dāng)客戶計(jì)算機(jī)需要連接時(shí)就會(huì)發(fā)生 ConnectionRequest 事件。為了完成連接,可調(diào)用 ConnectionRequest 事件內(nèi)的 Accept 方法。
建立連接后,任何一方計(jì)算機(jī)都可以收發(fā)數(shù)據(jù)。為了發(fā)送數(shù)據(jù),可調(diào)用 SendData 方法。當(dāng)接收數(shù)據(jù)時(shí)會(huì)發(fā)生 DataArrival 事件。調(diào)用 DataArrival 事件內(nèi)的 GetData 方法就可獲取數(shù)據(jù)。
2、Winsock控件的常用屬性:
a、協(xié)議
在使用Winsock控件時(shí),首先需要考慮使用什么協(xié)議??梢允褂玫膮f(xié)議包括 TCP 和 UDP。兩種協(xié)議之間的重要區(qū)別在于它們的連接狀態(tài):
? TCP 協(xié)議控件是基于連接的協(xié)議,可以將它同電話系統(tǒng)相比。在開(kāi)始數(shù)據(jù)傳輸之前,用戶必須先建立連接。
? UDP 協(xié)議是一種無(wú)連接協(xié)議,兩臺(tái)計(jì)算機(jī)之間的傳輸類似于傳遞郵件:消息從一臺(tái)計(jì)算機(jī)發(fā)送到另一臺(tái)計(jì)算機(jī),但是兩者之間沒(méi)有明確的連接。另外,單次傳輸?shù)淖畲髷?shù)據(jù)量取決于具體的網(wǎng)絡(luò)。
在設(shè)計(jì)時(shí),可以按如下方式設(shè)置應(yīng)用程序使用的協(xié)議:在“屬性”窗口中單擊“協(xié)議”,然后選擇 sckTCPProtocol 或者 sckUDPProtocol。也可以使用程序代碼來(lái)設(shè)置 Protocol 屬性,如下所示:
Winsock1.Protocol = sckTCPProtocol
b、IP地址(計(jì)算機(jī)名稱)
客戶應(yīng)用程序在與遠(yuǎn)程計(jì)算機(jī)相連接的時(shí)候,需要知道遠(yuǎn)程計(jì)算機(jī)的 IP 地址或者計(jì)算機(jī)名稱。
我們連接計(jì)算機(jī)時(shí)可以將其作為 RemoteHost 屬性的值。代碼如下:
Winsock1.RemoteHost = 計(jì)算機(jī)名稱 或者為 Winsock1.RemoteHost =IP地址
服務(wù)器程序用到LocalIP 屬性,它返回本地機(jī)器的 IP 地址,格式是 IP 地址加點(diǎn)字符串 (xxx.xxx.xxx.xxx)。
用RemoteHostIP屬性返回遠(yuǎn)程計(jì)算機(jī)的IP。
c、端口號(hào)
對(duì)于客戶應(yīng)用程序來(lái)說(shuō),RemotePort 屬性最重要,它設(shè)置要連接的遠(yuǎn)程端口號(hào)。
對(duì)于服務(wù)器程序來(lái)說(shuō),LocalPort 屬性最重要,它設(shè)置所用到的本地端口。這是用于偵聽(tīng)的本地端口。如果指定的是端口 0,就使用一個(gè)隨機(jī)端口。在調(diào)用了 Listen 方法后,屬性就包含了已選定的實(shí)際端口。
3、Winsock控件的常用事件
a、Connect 事件
該事件是在到服務(wù)器的連接建立之后發(fā)生。
b、ConnectionRequest 事件
當(dāng)遠(yuǎn)程計(jì)算機(jī)請(qǐng)求連接時(shí)出現(xiàn)。
如果有連接請(qǐng)求時(shí),可以用 Accept 方法接受新連接。
c、DataArrival 事件
當(dāng)新數(shù)據(jù)到達(dá)時(shí)出現(xiàn)。
如果有新數(shù)據(jù)到達(dá)時(shí),可以用GetData方法接收數(shù)據(jù)。如果沒(méi)有獲取一個(gè) GetData 調(diào)用中的全部數(shù)據(jù),則事件不會(huì)出現(xiàn)。只有存在新數(shù)據(jù)時(shí)才激活事件??呻S時(shí)用 BytesReceived 屬性檢查可用的數(shù)據(jù)量。
4、Winsock控件的常用方法
a、Accept 方法
接受新連接。
僅適用于 TCP 服務(wù)器應(yīng)用程序。在處理 ConnectionRequest 事件時(shí)用這個(gè)方法接受新連接。在 ConnectionRequest 事件中使用 Accept 方法。ConnectionRequest 事件有一個(gè)對(duì)應(yīng)的參數(shù),即 RequestID 參數(shù)(新連接請(qǐng)求標(biāo)識(shí)),該參數(shù)應(yīng)該傳給 Accept 方法。
b、Bind 方法
指定用于 TCP 連接的 LocalPort(端口號(hào)) 和 LocalIP。(IP 地址)
在調(diào)用 Listen 方法之前必須調(diào)用 Bind 方法。
c、Close 方法
關(guān)閉連接。
d、GetData 方法
獲取當(dāng)前的數(shù)據(jù)塊并將其存儲(chǔ)在變體類型的變量中。
通??偸菍?GetData 方法與 DataArrival 事件并用。
e、Listen 方法
偵聽(tīng)模式。該方法僅適用于 TCP 連接。
當(dāng)有新連接時(shí)就會(huì)出現(xiàn) ConnectionRequest 事件。處理ConnectionRequest 事件時(shí),應(yīng)用程序應(yīng)該(在一個(gè)新的控件示例上)用 Accept 方法接受連接。
f、SendData 方法
將數(shù)據(jù)發(fā)送給遠(yuǎn)程計(jì)算機(jī)。
大體了解了Winsock控件的使用之后,對(duì)理解GPRS通訊的原理來(lái)說(shuō),有一定的幫助。
接下來(lái)我們將根據(jù)Winsock控件的使用來(lái)大體理解GPRS通訊的原理。
1、啟動(dòng)服務(wù)
原理為建立一個(gè)Tcp的連接,首先設(shè)定數(shù)據(jù)業(yè)務(wù)中心的IP地址及監(jiān)聽(tīng)端口號(hào),將其賦給Winsock控件,并用該控件進(jìn)行連接,連接成功后,進(jìn)行監(jiān)聽(tīng)。
代碼如下:
myLocalIP = tcpServer(0).LocalIP‘本地機(jī)器的 IP 地址(局域網(wǎng)方式)
myLocalIP = “10.14.87.102”‘無(wú)線Modem的IP地址(撥號(hào)上網(wǎng)方式)
PlngTCPLocalPort = 2020 ‘Tcp服務(wù)器的監(jiān)聽(tīng)端口號(hào)
Winsock.Bind (Port ,IP)
Winsock.Listen
需要注意的是如果計(jì)算機(jī)上既有本地連接又有無(wú)線Modem,在運(yùn)行程序(啟動(dòng)服務(wù))時(shí)有可能失敗,所以,在編寫(xiě)代碼的時(shí)候一定要注意自己使用的是哪種方式。因?yàn)長(zhǎng)ocalIP屬性獲取的是本地連接的IP,用無(wú)線Modem的時(shí)候IP最好是直接賦值。
再者就是兩者同時(shí)使用的時(shí)候,如果用的是無(wú)線Modem的撥號(hào)連接,則本地連接只能是同一個(gè)網(wǎng)段內(nèi)使用。
2、GPRS模塊連接請(qǐng)求處理
代碼如下:
Public Sub Winsock_ConnectionRequest(ByVal RequestID As Long)
Winsock.Accept Requested‘接收新連接
End Sub
原理為如果現(xiàn)在有連接請(qǐng)求,先把請(qǐng)求連接的GPRS模塊的IP地址記錄下來(lái)(用的是Winsock控件的RemoteHostIP屬性),再判斷保存所有GPRS模塊信息的數(shù)組中是否出現(xiàn)過(guò),如果沒(méi)有出現(xiàn)過(guò),保存該信息;如果出現(xiàn)過(guò),先卸載該控件,然后重新加載該控件,保存信息。
3、GPRS模塊數(shù)據(jù)通訊處理
代碼如下:
Public Sub Winsock_DataArrival(ByVal bytesTotal As Long)
GprsLong = Winsock.BytesReceived‘返回接收到的(當(dāng)前在接收端緩沖區(qū)內(nèi)的)數(shù)據(jù)的數(shù)量
Winsock.GetData TempArr, vbByte‘用 GetData 方法來(lái)獲取數(shù)據(jù),取得的數(shù)據(jù)存放在TempArr中。
End Sub
原理為如果下面的GPRS模塊向數(shù)據(jù)業(yè)務(wù)中心發(fā)送數(shù)據(jù),數(shù)據(jù)業(yè)務(wù)中心用GetData方法將數(shù)據(jù)從接收緩沖區(qū)中讀出來(lái),然后根據(jù)條件進(jìn)行判斷所收到的數(shù)據(jù)是否正確。
在用GetData方法進(jìn)行數(shù)據(jù)接收時(shí)需要注意是用哪種方式進(jìn)行通訊的,收到的數(shù)是Hex還是Ascii,這里接收的方式不一樣。如果是Ascii方式,接收的數(shù)據(jù)要賦給一個(gè)字符串變量,方式為:Winsock.GetData TempStr, vbString;如果是Hex方式,接收的數(shù)據(jù)要賦給一個(gè)以Byte 數(shù)據(jù)類型的數(shù)組,方式為:Winsock.GetData TempArr, vbByte 。
在接收數(shù)據(jù)之后,必須先要進(jìn)行數(shù)據(jù)編譯,如果碰到‘80H和90H’在一塊的將其轉(zhuǎn)換成為‘1AH’,碰到‘8AH和9AH’在一塊的將其轉(zhuǎn)換成為‘8AH’。
將接收到的數(shù)據(jù)進(jìn)行編譯之后,就可根據(jù)條件進(jìn)行數(shù)據(jù)處理了。
4、數(shù)據(jù)中心發(fā)送數(shù)據(jù)
代碼如下:
以十六進(jìn)制發(fā)送數(shù)據(jù)時(shí)為:
Dim Cmd(1 to 7) As Byte
Cmd(1)=&H4C
Cmd(2)=&H57
Cmd(3)=&H01
Cmd(4)=&H00
Cmd(5)=&H20
Cmd(6)=&H21
Cmd(7)=&H0D
Winsock.SendData Cmd
以Ascii方式發(fā)送數(shù)據(jù)為:
dim Cmd as string
Cmd=”#01A”+chr(13)
Winsock.SendData Cmd
原理為發(fā)送數(shù)據(jù)時(shí),要知道該GPRS模塊的ID號(hào)和發(fā)送的數(shù)據(jù)。程序在發(fā)送時(shí),先判斷該ID號(hào)是否收到過(guò),如果沒(méi)有收到過(guò),程序就不向外發(fā)送數(shù)據(jù);如果收到過(guò),在發(fā)送的時(shí)候還要判斷GPRS模塊當(dāng)前的狀態(tài)(是否在線),只有所有條件都符合,才進(jìn)行發(fā)送數(shù)據(jù)命令。否則程序會(huì)出現(xiàn)錯(cuò)誤,提示網(wǎng)絡(luò)連接失敗,不能發(fā)送數(shù)據(jù)。
5、停止服務(wù)
代碼如下:
Winsock.Close
原理為如果用戶要關(guān)閉服務(wù)的話,先關(guān)閉所有控件的連接,并把所有加載的控件卸載掉,清空存放GPRS模塊的信息,將數(shù)據(jù)返回長(zhǎng)度置為0。
評(píng)論
查看更多