對於許多初學者來說,網路通訊程式的開發,普遍的乙個現象就是覺得難以入手。許多概念,諸如:同步(sync)/非同步(async),阻塞(block)/非阻塞(unblock)等,初學者往往迷惑不清,只知其所以而不知起所以然。
同步方式指的是傳送方不等接收方響應,便接著發下個資料報的通訊方式;而非同步指傳送方發出資料後,等收到接收方發回的響應,才發下乙個資料報的通訊方式。
阻塞套接字是指執行此套接字的網路呼叫時,直到成功才返回,否則一直阻塞在此網路呼叫上,比如呼叫recv()函式讀取網路緩衝區中的資料,如果沒有資料到達,將一直掛在recv()這個函式呼叫上,直到讀到一些資料,此函式呼叫才返回;而非阻塞套接字是指執行此套接字的網路呼叫時,不管是否執行成功,都立即返回。比如呼叫recv()函式讀取網路緩衝區中資料,不管是否讀到資料都立即返回,而不會一直掛在此函式呼叫上。在實際windows網路通訊軟體開發中,非同步非阻塞套接字是用的最多的。平常所說的c/s(客戶端/伺服器)結構的軟體就是非同步非阻塞模式的。
對於這些概念,初學者的理解也許只能似是而非,我將用乙個最簡單的例子說明非同步非阻塞socket的基本原理和工作機制。目的是讓初學者不僅對socket非同步非阻塞的概念有個非常透徹的理解,而且也給他們提供乙個用socket開發網路通訊應用程式的快速入門方法。作業系統是windows 98(或nt4.0),開發工具是visual c++6.0。
mfc提供了乙個非同步類casyncsocket,它封裝了非同步、非阻塞socket的基本功能,用它做常用的網路通訊軟體很方便。但它遮蔽了socket的非同步、非阻塞等概念,開發人員無需了解非同步、非阻塞socket的原理和工作機制。因此,建議初學者學習編網路通訊程式時,暫且不要用mfc提供的類,而先用winsock2 api,這樣有助於對非同步、非阻塞socket程式設計機制的理解。
為了簡單起見,伺服器端和客戶端的應用程式均是基於mfc的標準對話方塊,網路通訊部分基於winsock2 api實現。
先做伺服器端應用程式。
用mfc嚮導做乙個基於對話方塊的應用程式socketsever,注意第三步中不要選上windwos sockets選項。在做好工程後,建立乙個seversock,將它設定為非同步非阻塞模式,並為它註冊各種網路非同步事件,然後與自定義的網路非同步事件聯絡上,最後還要將它設定為監聽模式。在自定義的網路非同步事件的**函式中,你可以得到各種網路非同步事件,根據它們的型別,做不同的處理。下面將詳細介紹如何編寫相關**。
在socketseverdlg.h檔案的類定義之前增加如下定義:
#define network_event wm_user+166 file://定義網路事件
socket serversock; file://伺服器端socket
在類定義中增加如下定義:
class csocketseverdlg : cdialog
; 在socketseverdlg.cpp檔案中增加訊息對映,其中onnetevent是非同步事件**函式名:
on_message(network_event,onnetevent)
定義初始化網路函式,在socketseverdlg.cpp檔案的oninitdialog()中調此函式即可。
bool csocketseverdlg::initnetwork()
file://建立伺服器端套接字
serversock = socket(af_inet, sock_stream, ipproto_tcp); //udp用sock_dgram
if(serversock == invalid_socket)
file://繫結到本地乙個埠上
sockaddr_in localaddr;
localaddr.sin_family = af_inet;
localaddr.sin_port = htons(8888); file://埠號不要與其他應用程式衝突
localaddr.sin_addr.s_addr = 0;
if(bind(serversock ,(struct sockaddr*)&localaddr,sizeof(sockaddr))
= = socket_error)
file://將seversock設定為非同步非阻塞模式,並為它註冊各種網路非同步事件,其 中 m_hwnd
file://為應用程式的主對話方塊或主視窗的控制代碼
if(wsaasyncselect(serversock, m_hwnd, network_event,
fd_accept | fd_close | fd_read | fd_write) == socket_error)
listen(serversock, 5); file://設定偵聽模式
return true;
} 下面定義網路非同步事件的**函式
void csocketseverdlg::onnetevent(wparam wparam, lparam lparam) }
以下是發生在相應socket上的各種網路非同步事件的處理函式,其中onaccept傳進來的引數是伺服器端建立的套接字,onclose()、onreceive()和onsend()傳進來的引數均是伺服器端在接受客戶端連線時新建立的用與此客戶端通訊的socket。
void csocketseverdlg::onaccept(socket cursock)
void csocketseverdlg::onclose(socet cursock)
void csocketseverdlg::onsend(socet cursock)
void csocketseverdlg::onreceive(socet cursock)
用同樣的方法建立乙個客戶端應用程式。初始化網路部分,不需要將套接字設定為監聽模式。註冊非同步事件時,沒有fd_accept,但增加了fd_connect事件,因此沒有onaccept()函式,但增加了onconnect()函式。向伺服器發出連線請求時,使用connect()函式,連線成功後,會響應到onconnect()函式中。下面是onconnect()函式的定義,傳進來的引數是客戶端socket和伺服器端發回來的連線是否成功的標誌。
void csocketclntdlg::onconnect(socket cursock, int error) }
定義onreceive()函式,處理網路資料到達事件;
定義onsend()函式,處理傳送網路資料事件;
定義onclose()函式,處理伺服器的關閉事件。
以上就是用基於windows訊息機制的非同步i/o模型做伺服器和客戶端應用程式的基本方法。另外還可以用事件模型、重疊模型或完成埠模型,讀者可以參考有關書籍。
VC 網路程式設計
服務端程式的編寫 1.建立套接字 socket 2.將套接字繫結到乙個本地位址和埠上.bind 3.將套接字設為監聽模式,準備接收客戶請求 listen 4.等待客戶請求到來,當請求到來後,接收連線請求,返回乙個新的對應於此次連線的套接字 accept 5.用返回的套接字和客戶端進行通訊 send ...
VC 網路程式設計基礎
osi七層網路模型 物理硬體層 表示計算機網路中的物理裝置,常見的有計算機網絡卡等 資料鏈路層 將傳輸資料進行壓縮與解壓縮 網路層 將傳輸資料進行網路傳輸 資料傳輸層 進行資訊的網路傳輸 會話層 建立物理網路的連線 表示層 將傳輸資料以某種格式進行表示 應用層 應用程式介面 tcp ip實際上是乙個...
網路程式設計入門
網路程式設計本質上要做的事情就是交流,我們先來分析一下人與人交流,見上圖,我們發現人與人的通訊是分層結構的,這裡以乙個人對另乙個人說 hello world!為例。1 乙個人說了 hello world!後它就是乙個資訊,這個是資訊首先可以直接說出來,我們也可以使用暗號來代替。這就是說資訊可以選擇明...