程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 基於多線程的客戶端/服務器套接字類

基於多線程的客戶端/服務器套接字類

編輯:關於.NET

這篇文章主要介紹如何設計基於多線程的客戶端/服務器套接字(socket)類。開發者/設計者可以根據具體的 需要決定是否選用另外的線程。在網絡上有許多其它的套接字類,但是沒有一個能夠向這個類一樣為你的應用程序 提供回調功能(事件監測)。本文設計的類能夠為你提供如下的事件監測:完成建立鏈接、放棄鏈接、鏈接失敗和 接收數據(包括0字節數據包)。

描述:

本文提供一種新的,同時支持TCP和UDP通訊的套接字類,與你可能在本站或其它地方發現的套接字編程文章相 比,本文設計的類有很多優點。首先,這個類沒有像其它類要求提供窗口句柄的限制,假如你僅僅要一個控制應用 程序的話,這個限制是不好的,所以,本文的類沒有這樣的限制。它也為你提供了自動線程支持功能,套接字通過 類的句柄進行鏈接或斷開鏈接操作,它也提供了目前為之我所見到的類所沒有的其它功能。此類同時支持客戶端和 服務器套接字,一個服務器端套接字能被指定為一個能夠接受很多鏈接的套接字,一個客戶端套接字能夠鏈接一個 服務器端套接字。你還可以使用這個類在不建立鏈接的情況下在兩個應用程序間進行通信。在第二種情況下,你可 以創建兩個UDP套接字(每個程序一個)。這個類在創建像聊天室程序,或者在兩個或更多IPC(進程間通信) 程序( 進程)時有助於減少編碼量。同時為具有TCP/IP錯誤處理的雙方提供可靠的通信支持。你可能會使用確定的IP地址 使數據傳遞到能夠被控制的目的地(僅僅對於UDP方式),這個類的TCP方式只能夠在相等的雙方進行通信。

現在還不熟悉IP套接字,下面的段落將對此類如何工作進行詳細的介紹。這有是本文的目標:解釋套接字對象 的基本功能。

TCP/IP 棧

TCP/IP 棧比OSI棧短。

TCP是面向連接的協議,UDP(用戶數據報協議)是面向無連接的協議。

IP數據報

IP層提供了一個無連接的,不可靠的傳輸機制。它認為每個數據包都是相互獨立的。任何數據報之間的連接必 須被更高的層支持。IP層提供一種包含自身數據頭的和校驗。數據頭包含數據報的源地址和目的地址。IP層通過網 絡處理路由。為了傳輸,它也提供將大的數據報截斷為許多小數據報,並在目的端將它們重新組合的機制。

UDP

UDP是無連接的,也是不可靠的。它將數據報內容的校驗和(checksum)和端口號加到IP地址上。

TCP

TCP在IP上提供一個邏輯的可靠的基於連接的協議,它提供一個虛擬的環路,這樣兩個程序就可以進行通信。

互聯網地址

為了使用一個服務,你首先要找到它。互聯網使用地址規劃計算機,這樣計算機就能夠被定位。IP地址是一個 整形32位整數,它編碼了一個網絡ID和相當多的地址。根據網絡地址的大小,網絡ID被分成了很多類。

網絡地址

A類網使用8位作為網絡地址,余下的24位表示其他的地址。B類網使用16位作為網絡地址,C類網使用24位作為 網絡地址,D類網使用全部的32位作為網絡地址

內網地址

在互聯網上,UNIX網絡被分為很多子網。現在有11個,對一個子網,並利用10位處理,允許表示1024個主機。

主機地址

在一個內網裡面,用8位表示主機地址。也就是在一個內網裡最後可以布置256台主機。

整個IP地址

這32位地址通常被“.”分為4段。

端口地址

一個服務存在於一個主機上,並被端口所知道。這是一個16位數,要發送一個消息給一個服務,你要發給正在 運行這個服務的主機的端口,這不是位置透明。當然,很多端口我們都是知道的。例如:

tcpmux 1 TCP echo 7 UDP echo 7 TCP systat 11 TCP netstat 15 TCP ftp-data 20 TCP File Transfer Protocol (data) ftp 21 TCP File Transfer Protocol smtp 25 TCP Simple Mail Transfer Protocol time 37 TCP Time Server time 37 UDP Time Server name 42 UDP Name Server whois 43 TCP nicname domain 53 UDP domain 53 TCP tftp 69 UDP rje 77 TCP finger 79 TCP link 87 TCP ttylink supdup 95 TCP hostname 101 TCP hostname pop-2 109 TCP Post Office Protocol uucp-path 117 TCP nntp 119 TCP Network News Transfer Protocol ntp 123 TCP Network Time Protocol

端口的1-255被TCP/IP保留,系統可能會保留更多。我們的程序要在1023以上的端口運行,利用getservbyname 函數可以得到服務已經注冊的端口。

套接字:

套接字是一種操作系統用來處理網絡連接的數據結構,當調用socket時創建套接字。它返回一個類似文件描述 符的整數值(句柄)。事實上,在windows系統下,在使用ReadFile函數和WriteFile函數時可以使用這個句柄。

#include <sys/types.h>
#include <sys/socket.h>
int socket(int family, int type, int protocol);

這裡的“family”在進行IP通信時要指定為 AF_INET,protocol可以為0,並且type要根據是TCP形式還是UDP形 式而定。兩個程序可以通過各自創建一個套接字,從而在網絡上進行連接,這就像一個管子的兩端,但事實上這個 管子並不存在。

基於連接(TCP)

一個程序(服務器端)通過使用套接字的bind(綁定)來監聽系統。這樣可以使其他的套接字發現它,然後它 通過在這個套接字上進行監聽,進而可以“accept”(接收)任何進入的消息。而其他的程序(客戶端)通過和服 務器的套接字建立連接,進而可以交換消息。雙方大量的消息通過這個通道可以發送出去。

服務器端:

Create endpoint (socket())
Bind address (bind())
Specify queue (listen())
Wait for connection (accept())
Transfer data (read()/write())

客戶端

Create endpoint (socket())
Connect to server (connect())
Transfer data (read()/write())

無連接(UDP)

在沒有連接的方案中,兩個套接字必須通過使用bind(綁定)使系統知道它們的存在。這是因為每個消息都被 單獨處理,所以客戶端每發送一個消息或數據的時候都要查找服務器端。每當調用bind函數,它都綁定到一個新的 端口,它不能綁定到一個已經存在的端口。假如你指定端口號為0,系統將自動為你分配一個未使用的端口號。因 為每次發送消息都存在這個額外的操作,所以程序不使用Read/Write函數,而使用recvfrom/sendto函數。這個函 數使用遠端服務器的地址作為套接字的參數,執行寫入操作。

服務器端:

Create endpoint (socket())
Bind address (bind())
Transfer data (sendto()/recvfrom())

客戶端

Create endpoint (socket())
Bind address (bind()) (optional if connect is called)
Connect to server (connect())
Transfer data (sendto()/recvfrom())

使用方法:

這個類可以用來創建TCP或UDP套接字。它的用法很簡單。首先,這個類對服務器端來說是未完成的,這個類必 須被派生。幸運的是,僅僅需要創建OnDataReceived 和OnEvent這兩個函數。默認函數什麼都不做。我們現在就創 建一個服務器端套接字,並啟動它,方法如下:

// To use TCP socket
// no smart addressing - we use connection oriented
m_SocketObject.SetSmartAddressing( false );
m_SocketObject.CreateSocket( m_strPort, AF_INET, SOCK_STREAM,0); // TCP
// To use UDP socket
m_SocketObject.SetSmartAddressing( true );
m_SocketObject.CreateSocket( m_strPort,
  AF_INET, SOCK_DGRAM, SO_BROADCAST); // UDP
// Now you may start the server/client thread to do the work for you...
m_SocketObject.WatchComm();

創建一個客戶端套接字,並啟動它,方法如下:

// To use TCP socket
m_SocketObject.ConnectTo( strServer, m_strPort, AF_INET, SOCK_STREAM); // TCP
// To use UDP socket
m_SocketObject.ConnectTo( strServer, m_strPort, AF_INET, SOCK_DGRAM); // UDP
// Now you may start the server/client thread to do the work for you...
m_SocketObject.WatchComm();

作者:Ernest Laurentin 翻譯:高慶余

文章來源:http://www.codeproject.com/KB/IP/serversocket.aspx

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved