四、 具體的內(nèi)部編程思路:
GPRS控件的編寫,我們用到的是Winsock控件,所以首先要先了解一下Winsock控件的使用。
1、Winsock控件的使用:
Winsock控件對(duì)用戶來說是不可見的,我們?cè)诰帉懣蛻舳嘶蚍?wù)器程序時(shí),通過設(shè)置控件的屬性并調(diào)用其方法即可實(shí)現(xiàn)數(shù)據(jù)的雙向交換。
如果創(chuàng)建客戶應(yīng)用程序,就必須知道服務(wù)器計(jì)算機(jī)名或者 IP 地址(RemoteHost 屬性),還要知道進(jìn)行“偵聽”的端口(RemotePort 屬性),然后調(diào)用 Connect 方法。
如果創(chuàng)建服務(wù)器應(yīng)用程序,就應(yīng)設(shè)置一個(gè)收聽端口(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é)議。可以使用的協(xié)議包括 TCP 和 UDP。兩種協(xié)議之間的重要區(qū)別在于它們的連接狀態(tài):
? TCP 協(xié)議控件是基于連接的協(xié)議,可以將它同電話系統(tǒng)相比。在開始數(shù)據(jù)傳輸之前,用戶必須先建立連接。
? UDP 協(xié)議是一種無連接協(xié)議,兩臺(tái)計(jì)算機(jī)之間的傳輸類似于傳遞郵件:消息從一臺(tái)計(jì)算機(jī)發(fā)送到另一臺(tái)計(jì)算機(jī),但是兩者之間沒有明確的連接。另外,單次傳輸?shù)淖畲髷?shù)據(jù)量取決于具體的網(wǎng)絡(luò)。
在設(shè)計(jì)時(shí),可以按如下方式設(shè)置應(yīng)用程序使用的協(xié)議:在“屬性”窗口中單擊“協(xié)議”,然后選擇 sckTCPProtocol 或者 sckUDPProtocol。也可以使用程序代碼來設(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)用程序來說,RemotePort 屬性最重要,它設(shè)置要連接的遠(yuǎn)程端口號(hào)。
對(duì)于服務(wù)器程序來說,LocalPort 屬性最重要,它設(shè)置所用到的本地端口。這是用于偵聽的本地端口。如果指定的是端口 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ù)。如果沒有獲取一個(gè) GetData 調(diào)用中的全部數(shù)據(jù),則事件不會(huì)出現(xiàn)。只有存在新數(shù)據(jù)時(shí)才激活事件。可隨時(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 方法
偵聽模式。該方法僅適用于 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通訊的原理來說,有一定的幫助。
接下來我們將根據(jù)Winsock控件的使用來大體理解GPRS通訊的原理。
1、啟動(dòng)服務(wù)
原理為建立一個(gè)Tcp的連接,首先設(shè)定數(shù)據(jù)業(yè)務(wù)中心的IP地址及監(jiān)聽端口號(hào),將其賦給Winsock控件,并用該控件進(jìn)行連接,連接成功后,進(jìn)行監(jiān)聽。
代碼如下:
myLocalIP = tcpServer(0).LocalIP‘本地機(jī)器的 IP 地址(局域網(wǎng)方式)
myLocalIP = “10.14.87.102”‘無線Modem的IP地址(撥號(hào)上網(wǎng)方式)
PlngTCPLocalPort = 2020 ‘Tcp服務(wù)器的監(jiān)聽端口號(hào)
Winsock.Bind (Port ,IP)
Winsock.Listen
需要注意的是如果計(jì)算機(jī)上既有本地連接又有無線Modem,在運(yùn)行程序(啟動(dòng)服務(wù))時(shí)有可能失敗,所以,在編寫代碼的時(shí)候一定要注意自己使用的是哪種方式。因?yàn)長(zhǎng)ocalIP屬性獲取的是本地連接的IP,用無線Modem的時(shí)候IP最好是直接賦值。
再者就是兩者同時(shí)使用的時(shí)候,如果用的是無線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地址記錄下來(用的是Winsock控件的RemoteHostIP屬性),再判斷保存所有GPRS模塊信息的數(shù)組中是否出現(xiàn)過,如果沒有出現(xiàn)過,保存該信息;如果出現(xiàn)過,先卸載該控件,然后重新加載該控件,保存信息。
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 方法來獲取數(shù)據(jù),取得的數(shù)據(jù)存放在TempArr中。
End Sub
原理為如果下面的GPRS模塊向數(shù)據(jù)業(yè)務(wù)中心發(fā)送數(shù)據(jù),數(shù)據(jù)業(yè)務(wù)中心用GetData方法將數(shù)據(jù)從接收緩沖區(qū)中讀出來,然后根據(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)是否收到過,如果沒有收到過,程序就不向外發(fā)送數(shù)據(jù);如果收到過,在發(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。
電子發(fā)燒友App








評(píng)論