基於Winsock API的VC網路程式設計實戰

2021-06-01 20:28:04 字數 4093 閱讀 3611

隨著計算機資訊技術的飛速發展,網際網路與人類社會的工作、生活越來越緊密相關,它已經成為人類獲取、交流資訊的重要途徑和手段。所以當前對於開發人員來說,網路程式設計已是必備的技能。本例項詳細介紹了如何利用winsock api編寫網路應用程式。

一、實現方法

在網路程式設計中最常用的方案便是client/server (客戶機/伺服器)模型。在這種方案中客戶應用程式向伺服器程式請求服務。乙個服務程式通常在乙個眾所周知的位址監聽對服務的請求,也就是說,服務程序一直處於休眠狀態,直到乙個客戶向這個服務的位址提出了連線請求。在這個時刻,服務程式被"驚醒"並且為客戶提供服務-對客戶的請求作出適當的反應。

為了方便這種client/server模型的網路程式設計,90年代初,由microsoft聯合了其他幾家公司共同制定了一套windows下的網路程式設計介面,即windows sockets規範,它不是一種網路協議,而是一套開放的、支援多種協議的windows下的網路程式設計介面。現在的winsock已經基本上實現了與協議無關,你可以使用winsock來呼叫多種協議的功能,但較常使用的是tcp/ip協議。socket實際在計算機中提供了乙個通訊埠,可以通過這個埠與任何乙個具有socket介面的計算機通訊。應用程式在網路上傳輸,接收的資訊都通過這個socket介面來實現。

微軟為visual c++定義了winsock類如casyncsocket類和派生於casyncsocket 的csocket類,它們簡單易用,讀者朋友當然可以使用這些類來實現自己的網路程式,但是為了更好的了解winsock api程式設計技術,我們這裡**怎樣使用底層的api函式實現簡單的 winsock 網路應用程式設計,分別說明如何在server端和client端操作socket,實現基於tcp/ip的資料傳送,最後給出相關的源**。

在vc中進行winsock的api程式設計開發的時候,需要在專案中使用下面的三個檔案,否則會出現編譯錯誤。

1.winsock.h: 這是winsock api的標頭檔案,需要包含在專案中。

2.wsock32.lib: winsock api連線庫檔案。在使用中,一定要把它作為專案的非預設的連線庫包含到專案檔案中去。

3.winsock.dll: winsock的動態連線庫,位於windows的安裝目錄下。

伺服器端操作 socket(套接字)

1.在初始化階段呼叫wsastartup()

此函式在應用程式中初始化windows sockets dll ,只有此函式呼叫成功後,應用程式才可以再呼叫其他windows sockets dll中的api函式。在程式中呼叫該函式的形式如下:wsastartup((word)((1<<8|1),(lpwsadata)&wsadata),其中(1<<8|1)表示我們用的是winsocket1.1版本,wsaata用來儲存系統傳回的關於winsocket的資料。

2、建立socket

初始化winsock的動態連線庫後,需要在伺服器端建立乙個監聽的socket,為此可以呼叫socket()函式用來建立這個監聽的socket,並定義此socket所使用的通訊協議。此函式呼叫成功返回socket物件,失敗則返回invalid_socket(呼叫wsagetlasterror()可得知原因,所有winsocket 的api函式都可以使用這個函式來獲取失敗的原因)。

socket pascal far socket( int af, int type, int protocol )

引數: af:目前只提供 pf_inet(af_inet);

type:socket 的型別 (sock_stream、sock_dgram);

protocol:通訊協定(如果使用者不指定則設為0);

如果要建立的是遵從tcp/ip協議的socket,第二個引數type應為sock_stream,如為udp(資料報)的socket,應為sock_dgram。

3、繫結埠

接下來要為伺服器端定義的這個監聽的socket指定乙個位址及埠(port),這樣客戶端才知道待會要連線哪乙個位址的哪個埠,為此我們要呼叫bind()函式,該函式呼叫成功返回0,否則返回socket_error。

int pascal far bind( socket s, const struct sockaddr far *name,int namelen );

參 數: s:socket物件名;

namelen:name的長度;

如果使用者不在意位址或埠的值,那麼可以設定位址為inaddr_any,及port為0,windows sockets 會自動將其設定適當之位址及port (1024 到 5000之間的值)。此後可以呼叫getsockname()函式來獲知其被設定的值。

4、監聽

當伺服器端的socket物件繫結完成之後,伺服器端必須建立乙個監聽的佇列來接收客戶端的連線請求。listen()函式使伺服器端的socket 進入監聽狀態,並設定可以建立的最大連線數(目前最大值限制為 5, 最小值為1)。該函式呼叫成功返回0,否則返回socket_error。

int pascal far listen( socket s, int backlog );

參 數: s:需要建立監聽的socket;

backlog:最大連線個數;

伺服器端的socket呼叫完listen()後,如果此時客戶端呼叫connect()函式提出連線申請的話,server 端必須再呼叫accept() 函式,這樣伺服器端和客戶端才算正式完成通訊程式的連線動作。為了知道什麼時候客戶端提出連線要求,從而伺服器端的socket在恰當的時候呼叫accept()函式完成連線的建立,我們就要使用wsaasyncselect()函式,讓系統主動來通知我們有客戶端提出連線請求了。該函式呼叫成功返回0,否則返回socket_error。

int pascal far wsaasyncselect( socket s, hwnd hwnd,unsigned int wmsg, long levent );

引數: s:socket 物件;

hwnd :接收訊息的視窗控制代碼;

wmsg:傳給視窗的訊息;

levent:被註冊的網路事件,也即是應用程式向視窗傳送訊息的網路事件,該值為下列值fd_read、fd_write、fd_oob、fd_accept、fd_connect、fd_close的組合,各個值的具體含意為fd_read:希望在套接字s收到資料時收到訊息;fd_write:希望在套接字s上可以傳送資料時收到訊息;fd_accept:希望在套接字s上收到連線請求時收到訊息;fd_connect:希望在套接字s上連線成功時收到訊息;fd_close:希望在套接字s上連線關閉時收到訊息;fd_oob:希望在套接字s上收到帶外資料時收到訊息。具體應用時,wmsg應是在應用程式中定義的訊息名稱,而訊息結構中的lparam則為以上各種網路事件名稱。所以,可以在視窗處理自定義訊息函式中使用以下結構來響應socket的不同事件:  

switch(lparam) 

5、伺服器端接受客戶端的連線請求

當client提出連線請求時,server 端hwnd視窗會收到winsock stack送來我們自定義的乙個訊息,這時,我們可以分析lparam,然後呼叫相關的函式來處理此事件。為了使伺服器端接受客戶端的連線請求,就要使用accept() 函式,該函式新建一socket與客戶端的socket相通,原先監聽之socket繼續進入監聽狀態,等待他人的連線要求。該函式呼叫成功返回乙個新產生的socket物件,否則返回invalid_socket。

socket pascal far accept( scoket s, struct sockaddr far *addr,int far *addrlen );

引數:s:socket的識別碼;

addrlen:addr的長度

6、結束 socket 連線

結束伺服器和客戶端的通訊連線是很簡單的,這一過程可以由伺服器或客戶機的任一端啟動,只要呼叫closesocket()就可以了,而要關閉server端監聽狀態的socket,同樣也是利用此函式。另外,與程式啟動時呼叫wsastartup()憨數相對應,程式結束前,需要呼叫 wsacleanup() 來通知winsock dll釋放socket所占用的資源。這兩個函式都是呼叫成功返回0,否則返回socket_error。

int pascal far closesocket( socket s );

引數:s:socket 的識別碼;

int pascal far wsacleanup( void );

引數: 無

UDP協議的WinSock API程式設計示例

server 端 word wversion wsadata wsadata sockaddr in server addr,client addr char buff 1024 wversion makeword 2,2 if wsastartup wversion,wsadata 0 socke...

VC 基於文件的列印

列印過程 onprepareprinting 函式進行列印中一些資訊的設定。onbeginprinting 函式建立列印資源。onpreparedc 函式設定具體列印一頁時的資訊。呼叫onprint 函式列印一頁。1 在利用嚮導生成單文件和多文件應用程式的過程中,使用者可以選擇應用程式是否支援列印和...

vc 基於UDP的對話程式

伺服器 include include int main if lobyte wsadata.wversion 1 hibyte wsadata.wversion 1 socket srvier socket af inet,sock dgram,0 sockaddr in addr srv add...