當前位置:名人名言大全網 - 短信平臺 - 在VB6.0中如何使用socket控件?

在VB6.0中如何使用socket控件?

用VB5中WinSock控件編寫網上聊天程序

Sockets是在Unix系統上提出來的,壹開始主要是用於本地通訊,但很快就應用到C/S體系上。MicroSoft公司在此基礎上創建了WinSock控件,專門用於Windows接口,與Sockets完全兼容。Winsock控件對用戶來說是不可見的,它提供了訪問 TCP 和 UDP 網絡服務的方便途徑。Microsoft Access、Visual Basic、Visual C++ 或 Visual FoxPro 的開發人員都可使用它。為編寫客戶或服務器應用程序,不必了解 TCP 的細節或調用低級的 Winsock APIs。通過設置控件的屬性並調用其方法就可輕易連接到壹臺遠程機器上去,並且還可雙向交換數據。下面就利用VB5中的WinSock控件編寫壹個網上聊天程序。

壹)網絡通信協議的基礎和選擇

1.1 TCP(數據傳輸協議)基礎

數據傳輸協議允許創建和維護與遠程計算機的連接。連接兩臺計算機就可彼此進行數據傳輸。

如果創建客戶應用程序,就必須知道服務器計算機名或者 IP 地址(RemoteHost 屬性),還要知道進行“偵聽”的端口(RemotePort 屬性),然後調用 Connect 方法。

如果創建服務器應用程序,就應設置壹個收聽端口(LocalPort 屬性)並調用 Listen 方法。當客戶計算機需要連接時就會發生 ConnectionRequest 事件。為了完成連接,可調用 ConnectionRequest 事件內的 Accept 方法。

建立連接後,任何壹方計算機都可以收發數據。為了發送數據,可調用 SendData 方法。當接收數據時會發生 DataArrival 事件。調用 DataArrival 事件內的 GetData 方法就可獲取數據。

1.2 UDP(用戶數據文報協議)基礎

用戶數據文報協議 (UDP) 是壹個無連接協議。跟 TCP 的操作不同,計算機並不建立連接。另外 UDP 應用程序可以是客戶機,也可以是服務器。

為了傳輸數據,首先要設置客戶計算機的 LocalPort 屬性。然後,服務器計算機只需將 RemoteHost 設置為客戶計算機的 Internet 地址,並將 RemotePort 屬性設置為跟客戶計算機的 LocalPort 屬性相同的端口,並調用 SendData 方法來著手發送信息。於是,客戶計算機使用 DataArrival 事件內的 GetData 方法來獲取已發送的信息。

1.3 選擇通訊協議

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

TCP 協議是有連接的協議,可以將它同電話系統相比。在開始數據傳輸之前,用戶必須先建立連接。

UDP 協議是壹種無連接協議,兩臺計算機之間的傳輸類似於傳遞郵件:消息從壹臺計算機發送到另壹臺計算機,但是兩者之間沒有明確的連接。另外,單次傳輸的最大數據量取決於具體的網絡。

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

1. 在收發數據的時候,應用程序是否需要得到客戶端或者服務器的確認信息?如果需要,使用 TCP 協議,在收發數據之前先建立明確的連接。

2. 數據量是否特別大(例如圖象與聲音文件)?在連接建立之後,TCP 協議將維護連接並確保數據的完整性。不過,這種連接需要更多的計算資源,因而是比較“昂貴”的。

3. 數據發送是間歇的,還是在壹個會話內?例如,如果應用程序在某個任務完成的時候需要通知某個計算機,UDP 協議是更適宜的。UDP 協議適合發送少量的數據。

通訊協議的選擇是通過設置WinSock的Protocol屬性來實現的。下面選擇TCP通訊協議編寫網上聊天程序,在此之前必須知道壹個極其重要的參數---服務器端的IP地址或計算機名。

二)確定計算機的名字

1. 在計算機的桌面上,右鍵單擊“網上鄰居”。

2. 選擇“屬性”。

3. 單擊“標識”選項卡。

4. 在“計算機名稱”框中可以找到計算機的名稱。

確定計算機的 IP地址

1. 單擊“任務條”上的“啟動”。

2. 選擇“運行”。

3. 若服務器端操作系統為win95則在“打開”中填入“winipcfg”,若服務器端操作系統為winnt則在“打開”中填入“ipconfig”。

4. 按下“確定”鍵。

上面找到的計算機名稱或IP地址可以作為WinSock的RemoteHost 屬性的值。

三) winsock控件的State屬性。

state 屬性的設置值是: 常 數

值 描 述

sckclosed 0 缺省的。關閉

sckopen 1 打開

scklistening 2 偵聽

sckconnectionpending 3 連接掛起

sckresolvinghost 4 識別主機

sckhostresolved 5 已識別主機

sckconnecting 6 正在連接

sckconnected 7 已連接

sckclosing 8 同級人員正在關閉連接

sckerror 9 錯誤

下面主要要用到sckClosed.sckConnected兩個State屬性的值。

四)網上聊天程序的編制

4.1 程序中服務器端所起的作用。

從圖示中可以看到服務器端的兩個winsock控件之間並不存在直接的通訊,同時sckServer1和sckClient2及sckServer2和sckClient1之間是不能直接通訊的。這也即是說若sckClient1向sckClient2發出信息,信息首先被sckServer1接受,sckServer1再將信息傳給程序的信息處理部分,信息處理部分再將處理好的信息傳給sckServer2,再由sckServer2傳給sckClient2。反之亦然。那麽服務器端的信息處理部分又進行什麽工作呢?

1. 對通訊的通道數作壹些限制。

2. 對使用後已關閉的通道,必須能夠重新使用以節省資源。

3. 必須對所傳遞的數據包信息作甑別,從而作出不同的處理。

通過解開數據的包頭就可區分不同的信息。

網上聊天有兩種方式:第壹種,以廣播方式;第二種,以點對點的方式。廣播方式即所有客戶都能收到某壹客戶發出的信息。點對點的方式即想說“悄悄話”的壹對客戶專門開辟了壹間談話的“小屋”,別的客戶不能“聽”到他們的談話。在下面的程序中將看到如何利用數據的不同包頭來區分用戶是想以廣播方式還是以點對點的方式進行談話的(點對點方式數據的包頭為“PT”,廣播方式則無包頭)。

4.2 客戶端的程序

1. 在客戶端創建壹個新的工程將其命名為“ClientPrj”

2. 將缺省窗體命名為 frmClient。

3. 將窗體的標題改為“Client”。

4. 在窗體中添加壹個 WinSock 控件,並將其命名為 tcpClient。

5. 在 frmClient 中添加壹個ListBox 控件。將其命名為lstReceive。

6. 在 frmClient 中添加壹個 TextBox 控件。將其命名為 txtSend。

7. 在窗體上放兩個 CommandButton 控件,並將其命名為 cmdConnect和cmdSent。

8. 將cmdConnect控件的標題改為 Connect, 將cmdSent控件的標題改為 Sent。

9. 在窗體中添加如下的代碼。

Private Sub cmdConnect_Click()

On Error GoTo ErrorPro

sckClient.Connect

Exit Sub

ErrorPro:

MsgBox "服務器未開或網絡出錯!"

End

End Sub

Private Sub cmdSent_Click()

sckClient.SendData txtSent.Text

End Sub

Private Sub Form_Load()

' RemoteComputerName為服務器端的計算機名或IP地址。

sckClient.RemoteHost = "RemoteComputerName"

sckClient.RemotePort = 1000

End Sub

Private Sub sckClient_Close()

MsgBox "服務器通道已關閉!"

End

End Sub

Private Sub sckClient_Connect()

MsgBox "連接成功!"

cmdConnect.Enabled = False

End Sub

Private Sub sckClient_DataArrival(ByVal bytesTotal As Long)

Dim s As String

sckClient.GetData s

lstReceive.AddItem s

End Sub

Private Sub sckClient_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, _ ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)

sckClient.Close

cmdConnect.Enabled = True

End Sub

4.3 服務器端的程序

1. 在服務器端創建壹個新的工程將其命名為“ServerPrj”。

2. 將缺省窗體命名為“frmServer”。

3. 在窗體中添加壹個ListBox控件,將其命名為“lstReceive”。

4. 在窗體中添加三個WinSock控件,將其分別命名為“sckListen”,sckBusy和“sckServer”並將“sckServer”的“Index”屬性設置為0。

5. 在窗體中添加如下代碼.。

'最大通道數

Private MaxChan As Integer

Private Sub Form_Load()

Dim i As Integer

MaxChan = 10

For i = 1 To MaxChan - 1

Load sckServer(i)

Next i

sckListen.LocalPort = 1000

sckListen.Listen

End Sub

Private Sub sckBusy_Close()

sckBusy.Close

End Sub

Private Sub sckBusy_DataArrival(ByVal bytesTotal As Long)

sckBusy.SendData "服務器忙,請稍後再連接!"

DoEvents

End Sub

Private Sub sckListen_ConnectionRequest(ByVal requestID As Long)

Dim i As Integer

'決定由哪壹Winsock接受請求

For i = 0 To MaxChan - 1

If sckServer(i).State = 0 Then

Exit For

End If

Next i

If sckServer(i).State = 0 Then

sckServer(i).Accept requestID

Exit Sub

End If

'如果所有Winsock都用完則由專門的“忙”Winsock接受請求,以免用戶要求得不到響應

sckBusy.Close

sckBusy.Accept requestID

End Sub

Private Sub sckListen_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, _ ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)

sckListen.Close

sckListen.LocalPort = 1000

sckListen.Listen

End Sub

Private Sub sckServer_Close(Index As Integer)

sckServer(Index).Close

End Sub

Private Sub sckServer_DataArrival(Index As Integer, ByVal bytesTotal As Long)

Dim s As String

Dim i As Integer

sckServer(Index).GetData s

If UCase(Left(Trim(s), 2)) = "PT" Then '判斷是否為悄悄話,點對點方式

If IsNumeric(Mid(Trim(s), 3, 1)) Then

i = Mid(Trim(s), 3, 1)

sckServer(i).SendData "Channel " & Index & " " & Right(Trim(s), Len(Trim(s)) - 3)

DoEvents

End If

Else '廣播方式

For i = 0 To MaxChan - 1

'利用winsock的State屬性給所有連接在服務器上的客戶發消息

If sckServer(i).State = 7 Then

sckServer(i).SendData "Channel " & Index & " " & Trim(s)

DoEvents

End If

Next i

End If

lstReceive.AddItem "Channel " & Index & " " & Trim(s)

End Sub

Private Sub sckServer_Error(Index As Integer, ByVal Number As Integer, Description As String, _

ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As _

Long, CancelDisplay As Boolean)

sckServer(Index).Close

End Sub

從程序中可以看到:第壹,程序中限制了通道數(10路)。第二,通過判斷WinSock控件的State屬性是否為0(關閉狀態),來重新使用已關閉的WinSock控件。第三,通過給WinSock控件傳遞的信息加上包頭,來對信息進行不同的處理(程序中若信息前加上了“PT"(Private Talk)+"通道數”的包頭,由此就知道客戶想要同擁有此“通道數”的另壹客戶進行“悄悄話”,否則就以廣播方式將信息發給所有客戶)。

五) 結束語

WinSock控件不僅僅是用來編制網上聊天程序,而且可以用來編制各種網絡遊戲或網絡通信程序。實際上WinSock控件是編制各種C/S程序的利器。在實際使用中通常是將WinSock控件封裝在Activex DLL(進程內)、Activex EXE(進程外)部件的類中(類中引用)來使用的。通過區分所傳信息前的不同的包頭,用RaiseEvent命令引發不同 的事件,再對事件分別進行處理。這樣不僅增加了程序的可調試性和安全性,而且更符合事件驅動編程方法的特點。