程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> VC++ >> 新手必學:windows網絡編程經典入門

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

編輯:VC++

  對於一個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編網絡程序的機制有一定理解,接下來你可以進行更精彩的編程, 不僅可以在網上傳輸普通數據,而且還
  以傳輸語音、視頻數據,你還可以自己做一個聊天室,和你的同學在實驗室的局域網裡可以共同分享你的成果。

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