當前位置:編程學習大全網 - 編程語言 - 怎樣學習Windows 網絡編程

怎樣學習Windows 網絡編程

新手必學:windows網絡編程經典入門

作者:huyoo

對於壹個windows網絡編程初學者,下面方法是經典入門。

初學者建議不要用MFC提供的類,而用windows API做壹個簡單服務器和客戶端,這樣有助於對socket編程機制的理解。

為了簡單起見,應用程序是基於MFC的標準對話框。

Winsock用WINDOWS API實現:

(1)服務器端有兩個線程:

主線程 — 妳需要編寫以下函數來實現

#define NETWORK_EVENT USER_MESSAGE+100 file://定義網絡事件

sockaddr_in clientaddr; file://暫時存放客戶端IP地址

file://自己定義消息映射函數,將上面定義的網絡事件映射到處理函數

file://OnNetEvent為網絡事件處理函數,它在下面定義

ON_MESSAGE(NETWORK_EVENT, OnNetEvent);

在妳對話框中的初始化函數中調用下面的初始化網絡的子函數

BOOL InitNetwork() file://初始化網絡

{

file://初始化TCP協議

BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData);

if(ret != 0)

{

MessageBox("初始化套接字失敗!");

return FALSE;

}

file://創建服務器端套接字

SOCKET serverSocket

= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(serverSocket == INVALID_SOCKET)

{

MessageBox("創建套接字失敗!");

closesocket(m_Socket);

WSACleanup();

return FALSE;

}

file://綁定到本地壹個端口上

sockaddr_in localaddr;

localaddr.sin_family = AF_INET;

localaddr.sin_port = htons(1688);

localaddr.sin_addr.s_addr = 0;

if(bind(serverSocket ,(const struct sockaddr*)&localaddr,

sizeof(sockaddr)) == SOCKET_ERROR)

{

MessageBox("綁定地址失敗!");

closesocket(m_Socket);

WSACleanup();

return FALSE;

}

file://註冊網絡異步事件,m_hWnd為應用程序的主對話框或主窗口的句柄

WSAAsyncSelect(serverSocket, m_hWnd, NETWORK_EVENT,

FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE);

listen(serverSocket, 5); file://設置偵聽模式

return TRUE;

}

file://定義網絡事件的響應函數

void OnNetEvent(WPARAM wParam, LPARAM lParam)

{

file://調用API函數,得到網絡事件類型

int iEvent = WSAGETSELECTEVENT(lParam);

file://得到發出此事件的客戶端套接字

SOCKET pSock = (SOCKET)wParam;

switch(iEvent)

{

case FD_ACCEPT: file://客戶端連接請求

{

OnAccept();

break;

}

case FD_CLOSE: file://客戶端斷開事件:

{

OnClose(pSock);

break;

}

case FD_READ: file://網絡數據包到達事件

{

OnReceive(pSock);

break;

}

case FD_WRITE: file://發送網絡數據事件

{

OnSend(pSock);

break;

}

default: break;

}

}

void OnAccept(SOCET pSock) file://響應客戶端連接請求函數

{

int len = sizeof(sockaddr);

file://調用API函數,接受連接,並返回壹個新套接字

file://還可以獲得客戶端的IP地址

SOCKET clientSocket = accept(serverSocket,

(struct sockaddr*)&clientaddr, &len);

file://為新的socket註冊異步事件,註意沒有Accept事件

if(WSAAsyncSelect(clientSocket ,m_hWnd, IP_EVENT,

FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)

{

MessageBox("註冊異步事件失敗!");

return;

  }

file://自編函數,將此客戶端的相關信息保存下來:套接字、

// IP地址、登陸時間

saveClientSocket(clientSocket,clientAddr,currentTimer);

}

void OnClose(SOCET pSock)

{

file://自編函數,結束與相應的客戶端的通信,釋放相應資源並做相應處理

endClientSocket(pSock);

}

void OnSend(SOCET pSock)

{

file://自編函數,在給客戶端發數據時做壹些預處理

handleOnSend(pSock);

}

void OnReceive(SOCET pSock)

{

recv(...); file://調用API函數,讀出網絡緩沖區中的數據包

file://自編函數,將此數據包和發出此數據的客戶端

file://clientSocket封裝成壹條網絡消息

buildNetMsg(...);

file://自編函數,將此網絡消息放入壹個消息隊列中,由工作線程去處理

saveNetMsg(...);

SetEvent(...); file://用事件對象觸發工作線程

}

客戶端登陸後,隨即把自己的計算機名發給服務器,服務器接到後,把它保存下來。這樣服務器就可以顯示所有在線客戶端的信息了,包括:客戶端計算機名、IP地址、登陸時間等。

註意: 客戶端沒有OnAccept()函數,但有OnConnect()函數。

工作線程 —

在妳的應用程序初始化時,創建並啟動壹個工作線程

AfxBeginThread(WorkThread,this,THREAD_PRIORITY_NORMAL);

file://this可能為應用程序的主對話框或主窗口的句柄

UINT WorkThread(LPVOID pParam)

{

while(1)

{

file://等待多重事件到來

int ret = WaitForMultipleObject(...);

switch(ret)

{

case OBJECT_0:

{

if(bNewNetMsg) file://查看網絡消息隊列是否有新的網絡消息

{

readNetMsg(...); file://如有新的網絡消息,則讀出

handleNetMsg(...); file://處理此網絡消息

}

break;

}

case OBJECT_0 + 1:

{

file://做退出處理

break;

}

default: break;

}

return 0;

}

客戶端為單線程,登陸服務器時,用connect()函數給服務器發連接請求;

客戶端沒有OnAccept()函數,但有OnConnect()函數。

在OnConnect()函數裏做發連接請求時的預處理;

在OnReceive()函數裏響應並處理網絡數據;

在OnClose()函數裏響應服務器的關閉事件;

在OnSend()函數裏做發數據時的預處理;

如果妳還想實現各客戶端之間的在線交流(即所謂的聊天室),妳在客戶端還可以基於UDP協議

再做壹套多點對多點的局域網組播模型模型,以後在和妳聊,妳先把上面的程序實現。

以上的I/O異步模型基於Windows的消息機制,另外還可以用事件模型、重疊模型或完成端口模型,

建議妳參考Windows網絡編程指南之類的書。

如果妳能對上面的機制很熟練,妳肯定已經對Winsock編網絡程序的機制有壹定理解,接下來妳可以進行更精彩的編程, 不僅可以在網上傳輸普通數據,而且還

以傳輸語音、視頻數據,妳還可以自己做壹個聊天室,和妳的同學在實驗室的局域網裏可以***同分享妳的成果。

  • 上一篇:零基礎可以學計算機嗎?
  • 下一篇:深圳小型松下電話交換機,松下電話系統TDA100的適用場所與企業,
  • copyright 2024編程學習大全網