C 中的Socket程式設計詳解

2021-07-09 19:24:47 字數 4809 閱讀 9578

microsoft.net framework為應用程式訪問internet提供了分層的、可擴充套件的以及受管轄的網路服務,其名字空間system.net和system.net.sockets包含豐富的類可以開發多種網路應用程式。.net類採用的分層結構允許應用程式在不同的控制級別上訪問網路,開發人員可以根據需要選擇針對不同的級別編制程式,這些級別幾乎囊括了internet的所有需要--從socket套接字到普通的請求/響應,更重要的是,這種分層是可以擴充套件的,能夠適應internet不斷擴充套件的需要。拋開iso/osi模型的7層構架,單從tcp/ip模型上的邏輯層面上看,.net類可以視為包含3個層次:請求/響應層、應用協議層、傳輸層。webreqeust和webresponse 代表了請求/響應層,支援http、tcp和udp的類組成了應用協議層,而socket類處於傳輸層。可以如下示意:

可見,傳輸層位於這個結構的最底層,當其上面的應用協議層和請求/響應層不能滿足應用程式的特殊需要時,就需要使用這一層進行socket套接字程式設計。

其實,socket可以象流stream一樣被視為乙個資料通道,這個通道架設在應用程式端(客戶端)和遠端伺服器端之間,而後,資料的讀取(接收)和寫入(傳送)均針對這個通道來進行。

可見,在應用程式端或者伺服器端建立了socket物件之後,就可以使用send/sentto方法將資料傳送到連線的socket,或者使用receive/receivefrom方法接收來自連線socket的資料;

針對socket程式設計,.net 框架的 socket 類是 winsock32 api 提供的套接字服務的託管**版本。其中為實現網路程式設計提供了大量的方法,大多數情況下,socket 類方法只是將資料封送到它們的本機 win32 副本中並處理任何必要的安全檢查。如果你熟悉winsock api函式,那麼用socket類編寫網路程式會非常容易,當然,如果你不曾接觸過,也不會太困難,跟隨下面的解說,你會發覺使用socket類開發windows 網路應用程式原來有規可尋,它們在大多數情況下遵循大致相同的步驟。

在使用之前,你需要首先建立socket物件的例項,這可以通過socket類的構造方法來實現:

public socket(addressfamily addressfamily,sockettype sockettype,protocoltype protocoltype);

其中,addressfamily 引數指定 socket 使用的定址方案,sockettype 引數指定 socket 的型別,protocoltype 引數指定 socket 使用的協議。

socket s = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp);

若要使用 udp 而不是 tcp,需要更改協議型別,如下面的示例所示:

socket s = new socket(addressfamily.internetwork, sockettype.dgram, protocoltype.udp);

一旦建立 socket,在客戶端,你將可以通過connect方法連線到指定的伺服器,並通過send/sendto方法向遠端伺服器傳送資料,而後可以通過receive/receivefrom從服務端接收資料;而在伺服器端,你需要使用bind方法繫結所指定的介面使socket與乙個本地終結點相聯,並通過listen方法偵聽該介面上的請求,當偵聽到使用者端的連線時,呼叫accept完成連線的操作,建立新的socket以處理傳入的連線請求。使用完 socket 後,記住使用 shutdown 方法禁用 socket,並使用 close 方法關閉 socket。其間用到的方法/函式有:

socket.connect方法:建立到遠端裝置的連線 

public void connect(endpoint remoteep)(有過載方法) 

socket.send 方法:從資料中的指示位置開始將資料傳送到連線的 socket。 

public int send(byte, int, socketflags);(有過載方法) 

socket.sendto 方法 將資料傳送到特定終結點。 

public int sendto(byte, endpoint);(有過載方法) 

socket.receive方法:將資料從連線的 socket 接收到接收緩衝區的特定位置。 

public int receive(byte,int,socketflags); 

socket.receivefrom方法:接收資料緩衝區中特定位置的資料並儲存終結點。 

public int receivefrom(byte, int, socketflags, ref endpoint); 

socket.bind 方法:使 socket 與乙個本地終結點相關聯: 

public void bind( endpoint localep ); 

socket.listen方法:將 socket 置於偵聽狀態。 

public void listen( int backlog ); 

socket.accept方法:建立新的 socket 以處理傳入的連線請求。 

public socket accept(); 

socket.shutdown方法:禁用某 socket 上的傳送和接收 

public void shutdown( socketshutdown how ); 

socket.close方法:強制 socket 連線關閉 

public void close();

可以看出,以上許多方法包含endpoint型別的引數,在internet中,tcp/ip 使用乙個網路位址和乙個服務埠號來唯一標識裝置。網路位址標識網路上的特定裝置;埠號標識要連線到的該裝置上的特定服務。網路位址和服務埠的組合稱為終結點,在 .net 框架中正是由 endpoint 類表示這個終結點,它提供表示網路資源或服務的抽象,用以標誌網路位址等資訊。.net同時也為每個受支援的位址族定義了 endpoint 的子代;對於 ip 位址族,該類為 ipendpoint。ipendpoint 類包含應用程式連線到主機上的服務所需的主機和埠資訊,通過組合服務的主機ip位址和埠號,ipendpoint 類形成到服務的連線點。

用到ipendpoint類的時候就不可避免地涉及到計算機ip位址,.net中有兩種類可以得到ip位址例項:

ipaddress類:ipaddress 類包含計算機在 ip 網路上的位址。其parse方法可將 ip 位址字串轉換為 ipaddress 例項。下面的語句建立乙個 ipaddress 例項:

ipaddress myip = ipaddress.parse("192.168.1.2");

dns 類:向使用 tcp/ip internet 服務的應用程式提供網域名稱服務。其resolve 方法查詢 dns 伺服器以將使用者友好的網域名稱(如"host.contoso.com")對映到數字形式的 internet 位址(如 192.168.1.1)。resolve方法 返回乙個 iphostenty 例項,該例項包含所請求名稱的位址和別名的列表。大多數情況下,可以使用 addresslist 陣列中返回的第乙個位址。下面的**獲取乙個 ipaddress 例項,該例項包含伺服器 host.contoso.com 的 ip 位址。

iphostentry iphostinfo = dns.resolve("host.contoso.com"); 

ipaddress ipaddress = iphostinfo.addresslist[0];

你也可以使用gethostname方法得到iphostentry例項:

iphosntentry hostinfo=dns.gethostbyname("host.contoso.com")

在使用以上方法時,你將可能需要處理以下幾種異常:

socketexception異常:訪問socket時作業系統發生錯誤引發

argumentnullexception異常:引數為空引用引發

objectdisposedexception異常:socket已經關閉引發

在掌握上面得知識後,下面的**將該伺服器主機( host.contoso.com的 ip 位址與埠號組合,以便為連線建立遠端終結點:

ipendpoint ipe = new ipendpoint(ipaddress,11000);

確定了遠端裝置的位址並選擇了用於連線的埠後,應用程式可以嘗試建立與遠端裝置的連線。下面的示例使用現有的 ipendpoint 例項與遠端裝置連線,並捕獲可能引發的異常:

try  

//處理引數為空引用異常 

catch(argumentnullexception ae) ", ae.tostring()); 

} //處理作業系統異常 

catch(socketexception se) ", se.tostring()); 

} catch(exception e) ", e.tostring()); 

}需要知道的是:socket 類支援兩種基本模式:同步和非同步。其區別在於:在同步模式中,對執行網路操作的函式(如 send 和 receive)的呼叫一直等到操作完成後才將控制返回給呼叫程式。在非同步模式中,這些呼叫立即返回。

另外,很多時候,socket程式設計視情況不同需要在客戶端和伺服器端分別予以實現,在客戶端編制應用程式向服務端指定埠傳送請求,同時編**務端應用程式處理該請求,這個過程在上面的闡述中已經提及;當然,並非所有的socket程式設計都需要你嚴格編寫這兩端程式;視應用情況不同,你可以在客戶端構造出請求字串,伺服器相應埠捕獲這個請求,交由其公用服務程式進行處理。以下事例語句中的字串就向遠端主機提出頁面請求:

遠端主機指定埠接受到這一請求後,就可利用其公用服務程式進行處理而不需要另行編**務器端應用程式。

C 中Socket網路程式設計例項詳解

c 中socket網路程式設計例項詳解 現在幾乎所有c c 的後台程式都需要進行網路通訊,其實現方法無非有兩種 使用系統底層socket或者使用已有的封裝好的網路庫。本文對兩種方式進行總結,並介紹乙個輕量級的網路通訊庫zeromq。1.基本的scoket程式設計 關於基本的scoket程式設計網路上...

C 中socket程式設計

摘自 sockets 套接字 程式設計有三種,流式套接字 sock stream 資料報套接字 sock dgram 原始套接字 sock raw 基於tcp的socket程式設計是採用的流式套接字。伺服器端程式設計的步驟 1 載入套接字型檔,建立套接字 wsastartup socket 2 繫結...

C 中socket程式設計

摘自 sockets 套接字 程式設計有三種,流式套接字 sock stream 資料報套接字 sock dgram 原始套接字 sock raw 基於tcp的socket程式設計是採用的流式套接字。伺服器端程式設計的步驟 1 載入套接字型檔,建立套接字 wsastartup socket 2 繫結...