<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    大鳥的學習樂園
    路漫漫其修遠兮,吾將上下而求索
    posts - 26,comments - 27,trackbacks - 0
    用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命令引發不同 的事件,再對事件分別進行處理。這樣不僅增加了程序的可調試性和安全性,而且更符合事件驅動編程方法的特點。
    posted on 2009-08-21 13:54 大鳥 閱讀(1970) 評論(0)  編輯  收藏 所屬分類: VBA
    主站蜘蛛池模板: 亚洲AV无码乱码在线观看牲色| 少妇无码一区二区三区免费| 好男人视频在线观看免费看片| 亚洲高清不卡视频| 91福利视频免费| 亚洲日产2021三区| 国产桃色在线成免费视频| 色婷五月综激情亚洲综合 | h片在线播放免费高清| 亚洲国产精品人人做人人爱| 美女免费视频一区二区三区| 亚洲国产黄在线观看| 丰满人妻一区二区三区免费视频| 夜夜春亚洲嫩草影院| 日本免费久久久久久久网站| 亚洲第一成年网站大全亚洲| 最新仑乱免费视频| 小说专区亚洲春色校园| 三上悠亚亚洲一区高清| 国产又黄又爽胸又大免费视频 | 久久久亚洲精品无码| 人与禽交免费网站视频| 亚洲日本VA中文字幕久久道具| 国产高清免费观看| 久久精品免费大片国产大片| 在线观看亚洲人成网站| a毛片基地免费全部视频| jizzjizz亚洲日本少妇| 亚洲精品无码久久千人斩| 1000部羞羞禁止免费观看视频 | 亚洲人成网站18禁止| 日韩精品成人亚洲专区| 国产猛男猛女超爽免费视频| 亚洲精品亚洲人成在线播放| 四只虎免费永久观看| 野花香高清在线观看视频播放免费 | 国产aa免费视频| 无码人妻AV免费一区二区三区| 精品亚洲AV无码一区二区三区| 亚洲男人天堂2020| 永久在线免费观看|