Win32 API 之 socket網路編程

來源:互聯網
上載者:User

標籤:os   使用   檔案   ar   資料   art   代碼   log   amp   

對於許多初學者來說,網路通訊程式的開發,普遍的一個現象就是覺得難以入手。許多概念,諸如:同步(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
      {
                  …
       public:
          SOCKET ClientSock[CLNT_MAX_NUM]; file://儲存與用戶端通訊的Socket的數組

          /*各種網路非同步事件的處理函數*/
        void OnClose(SOCKET CurSock);    file://對端Socket斷開
         void OnSend(SOCKET CurSock);    file://發送網路資料包
        void OnReceive(SOCKET CurSock); file://網路資料包到達
        void OnAccept(SOCKET CurSock);   file://用戶端串連請求

         BOOL InitNetwork();   file://初始化網路函數
          void OnNetEvent(WPARAM wParam, LPARAM lParam); file://非同步事件回呼函數
                 …
      };
         
       在SocketSeverDlg.cpp檔案中增加訊息映射,其中OnNetEvent是非同步事件回呼函數名:
                ON_MESSAGE(NETWORK_EVENT,OnNetEvent)
       定義初始化網路函數,在SocketSeverDlg.cpp檔案的OnInitDialog()中調此函數即可。
       BOOL CSocketSeverDlg::InitNetwork()
       {
            WSADATA wsaData;

           file://初始化TCP協議
           BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData);
          if(ret != 0)
           {
                 MessageBox(‘初始化網路通訊協定失敗!‘);
                return FALSE;
           }

           file://建立伺服器端通訊端
           ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if(ServerSock == INVALID_SOCKET)
           {
                MessageBox(‘建立通訊端失敗!‘);
               closesocket(ServerSock);
               WSACleanup();
                return FALSE;
           }

           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)
          {
                MessageBox(‘綁定地址失敗!‘);
                closesocket(ServerSock);
                WSACleanup();
                return FALSE;
          }

          file://將SeverSock設定為非同步非阻塞模式,並為它註冊各種網路非同步事件,其 中    m_hWnd       
          file://為應用程式的主對話方塊或主視窗的控制代碼
         if(WSAAsyncSelect(ServerSock, m_hWnd, NETWORK_EVENT,
               FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)
          {
                MessageBox(‘註冊網路非同步事件失敗!‘);
                WSACleanup();
                return FALSE;
          }
          listen(ServerSock, 5); file://設定偵聽模式
         return TRUE;
      }

      下面定義網路非同步事件的回呼函數
      void CSocketSeverDlg::OnNetEvent(WPARAM wParam, LPARAM lParam)
      {
         file://調用Winsock API函數,得到網路事件類型
         int iEvent = WSAGETSELECTEVENT(lParam);
           
         file://調用Winsock API函數,得到發生此事件的用戶端通訊端
         SOCKET CurSock= (SOCKET)wParam;

         switch(iEvent)
         {
         case FD_ACCEPT:       file://用戶端串連請求事件
                 OnAccept(CurSock);
                 break;
         case FD_CLOSE:        file://用戶端斷開事件:
                 OnClose(CurSock);
                 break;
         case FD_READ:         file://網路資料包到達事件
                 OnReceive(CurSock);
                 break;
          case FD_WRITE:       file://發送網路資料事件
                 OnSend(CurSock);
                 break;
          default: break;
          }
      }
     
       以下是發生在相應Socket上的各種網路非同步事件的處理函數,其中OnAccept傳進來的參數是伺服器端建立的通訊端,OnClose()、OnReceive()和OnSend()傳進來的參數均是伺服器端在接受用戶端串連時新建立的用與此用戶端通訊的Socket。
     void CSocketSeverDlg::OnAccept(SOCKET CurSock)
     {
          file://接受串連請求,並儲存與發起串連請求的用戶端進行通訊Socket
      file://為新的socket註冊非同步事件,注意沒有Accept事件
     }

     void CSocketSeverDlg::OnClose(SOCET CurSock)
     {
         file://結束與相應的用戶端的通訊,釋放相應資源
     }

     void CSocketSeverDlg::OnSend(SOCET CurSock)
     {
         file://在給用戶端發資料時做相關預先處理
     }

     void CSocketSeverDlg::OnReceive(SOCET CurSock)
     {
         file://讀出網路緩衝區中的資料包
     }         
         
        用同樣的方法建立一個用戶端應用程式。初始化網路部分,不需要將通訊端設定為監聽模式。註冊非同步事件時,沒有FD_ACCEPT,但增加了FD_CONNECT事件,因此沒有OnAccept()函數,但增加了OnConnect()函數。向伺服器發出串連請求時,使用connect()函數,串連成功後,會響應到OnConnect()函數中。下面是OnConnect()函數的定義,傳進來的參數是用戶端Socket和伺服器端發回來的串連是否成功的標誌。
void CSocketClntDlg::OnConnect(SOCKET CurSock, int error)
{
     if(0 = = error)
     {
     if(CurSock = = ClntSock)
      MessageBox(‘串連伺服器成功!‘);
    }
}
     定義OnReceive()函數,處理網路資料到達事件;
     定義OnSend()函數,處理髮送網路資料事件;
     定義OnClose()函數,處理伺服器的關閉事件。
             
        以上就是用基於Windows訊息機制的非同步I/O模型做伺服器和用戶端應用程式的基本方法。另外還可以用事件模型、重疊模型或完成連接埠模型,讀者可以參考有關書籍。

Win32 API 之 socket網路編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.