|
━━━━━━━━━━━━━━━━━━━━━━━━━ 一、Winsock 控件工作原理 利用 w insock 控件可以與遠(yuǎn)程計(jì)算機(jī)建立連接,并通過(guò)用 戶(hù)數(shù)據(jù)文報(bào)協(xié)議 (U D P)或者傳輸控制協(xié)議 (TCP)進(jìn)行數(shù)據(jù)交 換。這兩種協(xié)議都可以用來(lái)創(chuàng)建客戶(hù)與服務(wù)器應(yīng)用程序。用途: (1)創(chuàng)建收集用戶(hù)信息的客戶(hù)端應(yīng)用程序,并將收集的信息 發(fā)送到某中央服務(wù)器; (2)創(chuàng)建一個(gè)服務(wù)器應(yīng)用程序,作為多個(gè)用戶(hù)的數(shù)據(jù)的匯入點(diǎn); (3)創(chuàng)建“聊天”應(yīng)用程序。
二、用 Winsock 控件進(jìn)行編程的過(guò)程 (一)選擇通訊協(xié)議 在使用 winsock 控件時(shí),首先需要考慮使用什么協(xié)議??? 以使用的協(xié)議包括 TCP 和 UDP。兩種協(xié)議之間的重要區(qū)別在 于它們的連接狀態(tài): TCP 協(xié)議控件是基于連接的協(xié)議。在開(kāi) 始數(shù)據(jù)傳輸之前,用戶(hù)必須先建立連接。UDP 協(xié)議是一種無(wú) 連接協(xié)議,消息從一臺(tái)計(jì)算機(jī)發(fā)送到另一臺(tái)計(jì)算機(jī),但是兩者 之間沒(méi)有明確的連接。 到底選擇哪一種協(xié)議通常是由需要?jiǎng)?chuàng) 建的應(yīng)用程序決定的。 下面的幾個(gè)問(wèn)題將有助于選擇適宜的協(xié)議: 在收發(fā)數(shù)據(jù)的時(shí)候,應(yīng)用程序是否需要得到客戶(hù)端或者服 務(wù)器的確認(rèn)信息?如果需要,使用 TCP 協(xié)議,在收發(fā)數(shù)據(jù)之 前先建立明確的連接。 數(shù)據(jù)量是否特別大(例如圖象與聲音文件)?在連接建立 之后,TCP 協(xié)議將維護(hù)連接并確保數(shù)據(jù)的完整性。不過(guò),這種 連接需要更多的計(jì)算資源,因而是比較“昂貴”的。 數(shù)據(jù)發(fā)送是間歇的,還是在一個(gè)會(huì)話內(nèi)?例如,如果應(yīng)用 程序在某個(gè)任務(wù)完成的時(shí)候需要通知某個(gè)計(jì)算機(jī),UDP 協(xié)議 是更適宜的。UDP 協(xié)議適合發(fā)送少量的數(shù)據(jù)。 (二)協(xié)議的設(shè)置 在設(shè)計(jì)時(shí),可以按如下方式設(shè)置應(yīng)用程序使用的協(xié)議:在 “屬性”窗口中單擊“協(xié)議”,然后選擇 sckTCPProtocol 或者 sckUDPProtocol。也可以使用程序代碼來(lái)設(shè)置 Protocol 屬性, 如下所示: Winsock1.Protocol = sckTCPProtocol (三)確定計(jì)算機(jī)的名稱(chēng) 在與遠(yuǎn)程計(jì)算機(jī)相連接的時(shí)候,需要知道它的 IP 地址或 者它的“好聽(tīng)的名字”。IP 地址是一串?dāng)?shù)字,每三個(gè)數(shù)字為一 組,中間用點(diǎn)隔開(kāi)(形如 xxx.xxx.xxx.xxx)。通常,最易記住 的是計(jì)算機(jī)的“好聽(tīng)的名字”。上面找到的計(jì)算機(jī)名稱(chēng)可以作 為 RemoteHost 屬性的值。 (四)TCP 連接初步 如果應(yīng)用程序要使用 TCP 協(xié)議,那么首先必須決定應(yīng)用程序 是服務(wù)器還是客戶(hù)端。如果要?jiǎng)?chuàng)建一個(gè)服務(wù)器端,那么應(yīng) 用程序需要“監(jiān)聽(tīng)”指定的端口。當(dāng)客戶(hù)端提出連接請(qǐng)求時(shí), 服務(wù)器端能夠接受請(qǐng)求并建立連接。在連接建立之后,客戶(hù)端 與服務(wù)器端可以自由地互相通訊。 下列步驟創(chuàng)建一個(gè)非常簡(jiǎn)單的服務(wù)器: (五)創(chuàng)建一個(gè) TCP 服務(wù)器 請(qǐng)按照以下步驟執(zhí)行: 創(chuàng)建新的 Standard EXE 工程。 將缺省窗體的名稱(chēng)改為 frmServer。 將窗體的標(biāo)題改為“TCP 服務(wù)器”。 在窗體中放入一個(gè) winsock 控件,并將它的名字改為 tcpServer。 在窗體上添加兩個(gè) TextBox 控件。將第一個(gè)命名為 txtSendD ata,第二個(gè)為 txtO utput。 為窗體添加如下的代碼。 Private Sub Form_Load() '將 LocalPort 屬性設(shè)置為一個(gè)整 數(shù),然后調(diào)用 Listen 方法。 tcpServer.LocalPort = 1001 tcpServer.Listen frmClient.Show '顯示客戶(hù)端的窗體。 End Sub Private Sub tcpServer_ConnectionRequest _ (ByVal requestID As Long) ' 檢查控件的 State 屬性是否為關(guān)閉的。 ' 如果不是,在接受新的連接之前先關(guān)閉此連接。 If tcpServer.State <> sckClosed Then _ tcpServer.Close ' 接受具有 requestID 參數(shù)的連接。 tcpServer.Accept requestID End Sub Private Sub txtSendData_Change() tcpServer.SendData txtSendData.Text ' 包含了要發(fā)送的數(shù)據(jù) End Sub Private Sub tcpServer_DataArrival _ (ByVal bytesTotal As Long) Dim strData As String tcpServer.GetData strData txtOutput.Text = strData End Sub (六)創(chuàng)建 TCP 客戶(hù) 按照以下步驟執(zhí)行 : 在工程中添加一個(gè)新的窗體,將其命名為 frmClient。 將窗體的標(biāo)題改為“TCP Client”。 在 窗 體 中 添 加一 個(gè) winsock 控 件 , 并 將 其 命名為 tcpClient。 在 frmClient 中添加兩個(gè) TextBox 控件。將第一個(gè)命名 為 txtSend,第二個(gè)為 txtOutput。 在窗體上放一個(gè) CommandButton 控件,并將其命名為 cmdConnect。 將 CommandButton 控件的標(biāo)題改為 Connect。 在窗體中添加如下的代碼。 Private Sub Form_Load() tcpClient.RemoteHost = "RemoteComputerName" tcpClient.RemotePort = 1001 End Sub Private Sub cmdConnect_Click() ' 調(diào)用 Connect 方法,初始化連接。 tcpClient.Connect End Sub Private Sub txtSendData_Change() tcpClient.SendData txtSend.Text End Sub Private Sub tcpClient_DataArrival _ (ByVal bytesTotal As Long) Dim strData As String tcpClient.GetData strData txtOutput.Text = strData End Sub 上面的代碼創(chuàng)建了一個(gè)簡(jiǎn)單的客戶(hù) / 服務(wù)器模式的應(yīng)用程 序。我們可以將兩者都運(yùn)行起來(lái):運(yùn)行工程,然后單擊“連接”。 在兩個(gè)窗體之一的 txtSendData 文本框中鍵入文本,可以看到 同樣的文字將出現(xiàn)在另一個(gè)窗體的 txtOutput 文本框中。 (七)創(chuàng)建 UDP 應(yīng)用程序 創(chuàng)建 UDP 應(yīng)用程序比創(chuàng)建 TCP 應(yīng)用程序還要簡(jiǎn)單,因 為 UDP 協(xié)議不需要顯式的連接。第四、五、六步驟不用設(shè)計(jì)。 在上面的 TCP 應(yīng)用程序中,一個(gè) winsock 控件必須顯式地進(jìn) 行“監(jiān)聽(tīng)”,另一個(gè)必須使用 Connect 方法初始化連接。UDP 協(xié) 議不需要顯式的連接。要在兩個(gè)控件中間發(fā)送數(shù)據(jù),需要完成 以下的三步(在連接的雙方): 將 RemoteHost 屬性設(shè)置為另一臺(tái)計(jì)算機(jī)的名稱(chēng)。 將 RemotePort 屬性設(shè)置為第二個(gè)控件的 LocalPort 屬 性。 調(diào)用 Bind 方法,指定使用的 LocalPort。 因?yàn)閮膳_(tái)計(jì)算機(jī)的地位可以看成“平等的”,這種應(yīng)用程 序也被稱(chēng)為點(diǎn)到點(diǎn)的。 為了具體說(shuō)明這個(gè)問(wèn)題,下面將創(chuàng)建一 個(gè)“聊天”應(yīng)用程序,兩個(gè)人可以通過(guò)它進(jìn)行實(shí)時(shí)的交談。 要?jiǎng)?chuàng)建一個(gè) UDP 伙伴,請(qǐng)按照以下步驟執(zhí)行: 創(chuàng)建一個(gè)新的 Standard EXE 工程。 將缺省的窗體的名稱(chēng)修改為 frmPeerA。 將窗體的標(biāo)題修改為“Peer A”。 在 窗 體 中 放 入 一 個(gè) winsock 控 件 , 并 將 其 命名為 udpPeerA。 在“屬性”頁(yè)上,單擊“協(xié)議”并將協(xié)議修改為UDPProtocol。 在窗體中添加兩個(gè) TextBox 控件。將第一個(gè)命名為 txtSend,第二個(gè)命名為 txtOutput。 為窗體增加如下的代碼。 Private Sub Form_Load() .RemoteHost = "PeerB" . RemotePort = 1001 ' 連接的端口號(hào)。 .Bind 1002 ' 綁定到本地的端口。 frmPeerB.Show ' 顯示第二個(gè)窗體。 End Sub Private Sub txtSend_Change() ' 在鍵入文本時(shí),立即將其發(fā)送出去。 udpPeerA.SendData txtSend.Text End Sub Private Sub udpPeerA_DataArrival _ (ByVal bytesTotal As Long) Dim strData As String udpPeerA.GetData strData txtOutput.Text = strData End Sub 要?jiǎng)?chuàng)建第二個(gè) UDP 伙伴,請(qǐng)按照以下步驟執(zhí)行: 在工程中添加一個(gè)標(biāo)準(zhǔn)窗體。 將窗體的名字修改為 frmPeerB。 將窗體的標(biāo)題修改為“Peer B”。 在窗體中放入一個(gè) winsock 控件,并將其命名為 udpPeerB。 在“屬性”頁(yè)上,單擊“協(xié)議”并將協(xié)議修改為 “UDPProtocol”。 在窗體上添加兩個(gè) TextBox 控件。將第一個(gè)命名為 txtSend,第二個(gè)命名為 txtOutput。 在窗體中添加如下的代碼。 Private Sub Form_Load() RemoteHost = "PeerA" RemotePort = 1002 ' 要連接的端口。 Bind 1001 ' 綁定到本地的端口上。 End Sub Private Sub txtSend_Change() udpPeerB.SendData txtSend.Text End Sub Private Sub udpPeerB_DataArrival _ (ByVal bytesTotal As Long) Dim strData As String udpPeerB.GetData strData txtOutput.Text = strData End Sub 如果要試用上面的例子,按 F5 鍵運(yùn)行工程,然后在兩個(gè) 窗體的 txtSend TextBox 中分別鍵入一些文本。鍵入的文字將 出現(xiàn)在另一個(gè)窗體的 txtOutput TextBox 中。 三、結(jié)束語(yǔ) 上面介紹了在 vb6.0 下進(jìn)行 winsock 控件的編程方法與技 巧,在實(shí)際的應(yīng)用中,vb 可以直接調(diào)用 winsock 控件,這讓我 們?cè)?nbsp;vb 下面編寫(xiě)網(wǎng)絡(luò)通訊程序變的簡(jiǎn)單和愉快。 [責(zé)任編輯:尤書(shū)才] |
|
|