[轉]VB Winsock 控件TCP與UDP連接實例


 

利用 WinSock 控件可以與遠程計算機建立連接,並通過用戶數據文報協議 (UDP)或者傳輸控制協議 (TCP)進行數據交換。這兩種協議都可以用來創建客戶與服務器應用程序。與 Timer 控件類似,WinSock 控件在運行時是不可見的。

可能的用途

  • 創建收集用戶信息的客戶端應用程序,並將收集的信息發送到某中央服務器。
     
  • 創建一個服務器應用程序,作為多個用戶的數據的匯入點。
     
  • 創建“聊天”應用程序。

選擇通訊協議

在使用 WinSock 控件時,首先需要考慮使用什么協議。可以使用的協議包括 TCP 和 UDP。兩種協議之間的重要區別在於它們的連接狀態:

  • TCP 協議控件是基於連接的協議,可以將它同電話系統相比。在開始數據傳輸之前,用戶必須先建立連接。
     
  • UDP 協議是一種無連接協議,兩台計算機之間的傳輸類似於傳遞郵件:消息從一台計算機發送到另一台計算機,但是兩者之間沒有明確的連接。另外,單次傳輸的最大數據量取決於具體的網絡。

到底選擇哪一種協議通常是由需要創建的應用程序決定的。下面的幾個問題將有助於選擇適宜的協議:

  1. 在收發數據的時候,應用程序是否需要得到客戶端或者服務器的確認信息?如果需要,使用 TCP 協議,在收發數據之前先建立明確的連接。
     
  2. 數據量是否特別大(例如圖象與聲音文件)?在連接建立之后,TCP 協議將維護連接並確保數據的完整性。不過,這種連接需要更多的計算資源,因而是比較“昂貴”的。
     
  3. 數據發送是間歇的,還是在一個會話內?例如,如果應用程序在某個任務完成的時候需要通知某個計算機,UDP 協議是更適宜的。UDP 協議適合發送少量的數據。

協議的設置

在設計時,可以按如下方式設置應用程序使用的協議:在“屬性”窗口中單擊“協議”,然后選擇 sckTCPProtocol 或者 sckUDPProtocol。也可以使用程序代碼來設置 Protocol 屬性,如下所示:

Winsock1.Protocol = sckTCPProtocol

確定計算機的名稱

在與遠程計算機相連接的時候,需要知道它的 IP 地址或者它的“好聽的名字”。IP 地址是一串數字,每三個數字為一組,中間用點隔開(形如 xxx.xxx.xxx.xxx)。通常,最易記住的是計算機的“好聽的名字”。

要確定計算機的名字,請按照以下步驟執行:

  1. 在計算機的“任務欄”上,單擊“啟動”。
     
  2. 在“設置”項中,單擊“控制面板”。
     
  3. 雙擊“網絡”圖標。
     
  4. 單擊“標識”選項卡。
     
  5. 在“計算機名稱”框中可以找到計算機的名稱。

上面找到的計算機名稱可以作為 RemoteHost 屬性的值。

TCP 連接初步

如果應用程序要使用 TCP 協議,那么首先必須決定應用程序是服務器還是客戶端。如果要創建一個服務器端,那么應用程序需要“監聽”指定的端口。當客戶端提出連接請求時,服務器端能夠接受請求並建立連接。在連接建立之后,客戶端與服務器端可以自由地互相通訊。

下列步驟創建一個非常簡單的服務器:

要創建一個 TCP 服務器,請按照以下步驟執行:

  1. 創建新的 Standard EXE 工程。
     
  2. 將缺省窗體的名稱改為 frmServer。
     
  3. 將窗體的標題改為“TCP 服務器”。
     
  4. 在窗體中放入一個 Winsock 控件,並將它的名字改為 tcpServer。
     
  5. 在窗體上添加兩個 TextBox 控件。將第一個命名為 txtSendData,第二個為 txtOutput。
     
  6. 為窗體添加如下的代碼。
VBScript code 復制代碼
Private Sub Form_Load() '將 LocalPort 屬性設置為一個整數。 '然后調用 Listen 方法。 tcpServer.LocalPort = 1001 tcpServer.Listen frmClient.Show '顯示客戶端的窗體。 End Sub Private Sub tcpServer_ConnectionRequest _ (ByVal requestID As Long) '檢查控件的 State 屬性是否為關閉的。 '如果不是, '在接受新的連接之前先關閉此連接。 If tcpServer.State <> sckClosed Then _ tcpServer.Close '接受具有 requestID 參數的 '連接。 tcpServer.Accept requestID End Sub Private Sub txtSendData_Change() '名為 txtSendData 的 TextBox 控件中 '包含了要發送的數據。當用戶往文本框中 '鍵入數據時,使用 SendData 方法 '發送輸入的字符串。 tcpServer.SendData txtSendData.Text End Sub Private Sub tcpServer_DataArrival _ (ByVal bytesTotal As Long) '為進入的數據聲明一個變量。 '調用 GetData 方法,並將數據賦予名為 txtOutput '的 TextBox 的 Text 屬性。 Dim strData As String tcpServer.GetData strData txtOutput.Text = strData End Sub

上面的步驟創建了一個簡單的服務器應用程序。為了使它能夠工作,還必須為它創建一個客戶端的應用程序。

要創建 TCP 客戶端,請按照以下步驟執行:

  1. 在工程中添加一個新的窗體,將其命名為 frmClient。
     
  2. 將窗體的標題改為“TCP Client”。
     
  3. 在窗體中添加一個 Winsock 控件,並將其命名為 tcpClient。
     
  4. 在 frmClient 中添加兩個 TextBox 控件。將第一個命名為 txtSend,第二個為 txtOutput。
     
  5. 在窗體上放一個 CommandButton 控件,並將其命名為 cmdConnect。
     
  6. 將 CommandButton 控件的標題改為 Connect。
     
  7. 在窗體中添加如下的代碼。

重點   必須將 RemoteHost 屬性值修改為您的計算機的名字。

VBScript code 復制代碼
Private Sub Form_Load() 'Winsock 控件的名字為 tcpClient。 '注意:要指定遠程主機,可以使用 ' IP 地址(例如:"121.111.1.1"),也可以使用 '計算機的“好聽的名字”如下所示。 tcpClient.RemoteHost = "RemoteComputerName" tcpClient.RemotePort = 1001 End Sub Private Sub cmdConnect_Click() '調用 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

上面的代碼創建了一個簡單的客戶/服務器模式的應用程序。我們可以將兩者都運行起來:運行工程,然后單擊“連接”。在兩個窗體之一的 txtSendData 文本框中鍵入文本,可以看到同樣的文字將出現在另一個窗體的 txtOutput 文本框中。

接受多個連接請求

上面設計的基本服務器只能接受一個連接請求。通過創建控件數組,使用一個控件也可以同時接受多個連接請求。利用這種方法,不需要關閉連接,而只需創建新的控件實例(通過設置其索引屬性),然后在新的實例上調用 Accept 方法。

下面的代碼假定名為 sckServer 的窗體上有一個 Winsock 控件,它的 Index 屬性被設置為 0;因此控件是控件數組的一部分。在聲明部分,聲明了一個模塊級的變量 intMax。在窗體的 Load 事件中,intMax 被設置為 0,數組中第一個控件的 LocalPort 屬性被設置為 1001。然后調用控件的 Listen 方法,使之成為“監聽”控件。在連接請求到達時,代碼將檢測 Index 是否為 0(“監聽”控件的值)。如果為 0,監聽控件將增加 intMax 的值,並使用該號碼來創建新的控件實例。然后,使用新的控件實例接受連接請求。

VBScript code 復制代碼
Private intMax As Long Private Sub Form_Load() intMax = 0 sckServer(0).LocalPort = 1001 sckServer(0).Listen End Sub Private Sub sckServer_ConnectionRequest _ (Index As Integer, ByVal requestID As Long) If Index = 0 Then intMax = intMax + 1 Load sckServer(intMax) sckServer(intMax).LocalPort = 0 sckServer(intMax).Accept requestID Load txtData(intMax) End If End Sub

UDP 初步

創建 UDP 應用程序比創建 TCP 應用程序還要簡單,因為 UDP 協議不需要顯式的連接。在上面的 TCP 應用程序中,一個 Winsock 控件必須顯式地進行“監聽”,另一個必須使用 Connect 方法初始化連接。

UDP 協議不需要顯式的連接。要在兩個控件中間發送數據,需要完成以下的三步(在連接的雙方):

  1. 將 RemoteHost 屬性設置為另一台計算機的名稱。

     
  2. 將 RemotePort 屬性設置為第二個控件的 LocalPort 屬性。

     
  3. 調用 Bind 方法,指定使用的 LocalPort。(下面將詳細地討論該方法。)

因為兩台計算機的地位可以看成“平等的”,這種應用程序也被稱為點到點的。為了具體說明這個問題,下面將創建一個“聊天”應用程序,兩個人可以通過它進行實時的交談。

要創建一個 UDP 伙伴,請按照以下步驟執行:

  1. 創建一個新的 Standard EXE 工程。
     
  2. 將缺省的窗體的名稱修改為 frmPeerA。
     
  3. 將窗體的標題修改為“Peer A”。
     
  4. 在窗體中放入一個 Winsock 控件,並將其命名為 udpPeerA。
     
  5. 在“屬性”頁上,單擊“協議”並將協議修改為 UDPProtocol。
     
  6. 在窗體中添加兩個 TextBox 控件。將第一個命名為 txtSend,第二個命名為 txtOutput。
     
  7. 為窗體增加如下的代碼。
VBScript code 復制代碼
Private Sub Form_Load() '控件的名字為 udpPeerA With udpPeerA '重點:必須將 RemoteHost 的值 '修改為計算機的名字。 .RemoteHost = "PeerB" .RemotePort = 1001 '連接的端口號。 .Bind 1002 '綁定到本地的端口。 End With frmPeerB.Show '顯示第二個窗體。 End Sub Private Sub txtSend_Change() '在鍵入文本時,立即將其發送出去。 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

要創建第二個 UDP 伙伴,請按照以下步驟執行:

  1. 在工程中添加一個標准窗體。
     
  2. 將窗體的名字修改為 frmPeerB。
     
  3. 將窗體的標題修改為“Peer B”。
     
  4. 在窗體中放入一個 Winsock 控件,並將其命名為 udpPeerB。
     
  5. 在“屬性”頁上,單擊“協議”並將協議修改為“UDPProtocol”。
     
  6. 在窗體上添加兩個 TextBox 控件。將第一個命名為 txtSend,第二個命名為 txtOutput。
     
  7. 在窗體中添加如下的代碼。
VBScript code 復制代碼
Private Sub Form_Load() '控件的名字為 udpPeerB。 With udpPeerB '重點:必須將 RemoteHost 的值改為 '計算機的名字。 .RemoteHost = "PeerA" .RemotePort = 1002 '要連接的端口。 .Bind 1001 '綁定到本地的端口上。 End With 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 鍵運行工程,然后在兩個窗體的 txtSend TextBox 中分別鍵入一些文本。鍵入的文字將出現在另一個窗體的 txtOutput TextBox 中。

關於 Bind 方法

在上面的代碼中,在創建 UDP 應用程序時調用了 Bind 方法,這是必須的。Bind 方法的作用是為控件“保留”一個本地端口。例如,如果將控件綁定到 1001 號端口,那么其它應用程序將不能使用該端口進行“監聽”。該方法阻止其它應用程序使用同樣的端口。

Bind 方法的第二個參數是任選的。如果計算機上存在多個網絡適配器,可以用 LocalIP 參數來指定使用哪一個適配器。如果忽略該參數,控件使用的將是計算機上“控制面板”設置中“網絡”控制面板對話框中列出的第一個適配器。

在使用 UDP 協議的時候,可以任意地改變 RemoteHost 和 RemotePort 屬性,同時始終保持綁定在同一個 LocalPort 上。TCP 協議與此不同,在改變 RemoteHost 和 RemotePort 屬性之前,必須先關閉連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM