基於訊息的非同步通訊端

來源:互聯網
上載者:User

標籤:非同步通訊端

         Windows通訊端在兩種模式下執行I/O操作,阻塞模式和非阻塞模式。在阻塞模式下,執行操作的函數會一直等待,不會立即返回,知道發送完資料或者接受完資料為止。這在一定條件下是對效能的浪費,例如recvfrom函數沒有收到資料的時候吧就會一直等待下去。

         為了提高系統的效能,Winsock提供了基於訊息的非同步socket。下面介紹主要的Socket非同步通訊函數。

<1>int       WSASyncSelect(SOCKET s,HWND hwnd,unsigned int uMsg,longlEvent);

         這個函數的作用是註冊一個lEvent事件,那麼當lEvent事件被觸發的時候(比如註冊FD_READ,那麼一旦有資料發送過來,那麼就會觸發lEvent事件),系統就會發送一個uMsg訊息,發送的視窗就是hwnd控制代碼所指向的視窗。

<2>int       WSAEnumProtocols(LPINT lpiProtocols, LPWSAPROTOCOL_INFOlpProtocolBuffer,ILPDWORD lpdwBufferLength);

lpiProtocols:以NULL結尾的協議標識號數組,此參數可選,如果lpiProtocols為NULL,則函數返回所有可用協議的資訊,否則只返回數組中列出的協議資訊。

lpProtocolBuffer:out類型資料,作為返回值使用,一個用WSAPROTOCOL_INFO結構體填充的緩衝區。這個結構體用存放一個指定協議的完整資訊。

lpdwBufferLength :In/out型別參數,在輸入的時候,指定傳遞給lpProtocolBuffer緩衝區的長度,在輸出的時候,擷取存取所有請求資訊傳遞給WSAEnumProtocols函數的最小緩衝區的長度。

<3>int       WSASocket(int af,int type,intprotocol,LPWSAPROTOCOL_INFO,lpProtocolInfo,GROUP g,DWORD dwFlags);

lpProtocolInfo:指向 WSAPROTOCOL_INFO結構體的指標,該結構體指定了所建立通訊端的特性,如果lpProtocolInfo為NULL,則win32的Dll會使用前三個參數來決定使用哪一個服務提供者。

g:保留

dwFlags:指定通訊端屬性的描述。如果該參數為WSA_FLAG_OVERLAPPED,那麼將建立一個重疊通訊端。

<4> int WSARecvFrom(SOCKET s,LPWSABUFlpBuffers,DWORD dwBufferCount,LPDWORD lpNumerOfBytesRecvd,LPDWORDlpFlags,sockaddr *lpFrom,LPINT lpFromlen,LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINElpCompletionRoutine);

lpBuffers:in/out類型的參數,一個指向WSABUF結構體數組的指標,該結構體定義如下所示:

typedef struct  _WSABUF{u_long len;char *buf;}WSABUF,*LPWSABUF;

可見這個結構體就是指向的接受資料的緩衝區以及長度。

dwBufferCount:lpBuffers所指向的數組中WSABUF結構體的數目。

lpNumberOfBytesRecvd:out類型的參數,如果接受操作立即完成,那麼該參數是指向本次調用所接受位元組數的指標。

lpFlags:in/out類型的參數,一個指向標誌位的指標。

lpFrom:out類型的指標,是一個可選的指標,指向重疊操作完成後存放源地址的緩衝區。

lpFromlen:in/out類型的參數,一個指向lpFrom指定緩衝區大小的指標,僅當指定了lpFrom參數的時候才需要使用這個參數。

lpOverlapped:指向WSAOVERLAPPED結構體的指標,對於非重疊socket則忽略。

lpCompletionRoutine:一個指向接受操作完成時調用的完成常式的指標,對於非重疊socket則忽略。

<5>int     WSASendTo(SOCKET s,LPWSABUF lpBuffers,DWORDdwBufferCount,LPDWORD lpNumberOfByteSent,DWORD dwFlags,sockaddr* lpTo,intlen,LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINElpCompletionRoutine)

這個函數的參數是和WSARecvFrom的對應著,所以這個不用多說。

樣本程式:

下面是一個簡單的網路聊天程式,先說下它的流程:

1 載入通訊端庫

2 初始化並且綁定通訊端,中間包括自訂訊息的定義。

3 自訂訊息響應函數完成

4 發送訊息函數的完成。

核心代碼如下所示:

//socket lib loadBOOLCmfcAChatApp::InitInstance(){         //載入通訊端庫         WORD wVersionRequested;         WSADATA wsaData;         interr;         wVersionRequested = MAKEWORD(2,2);         err =WSAStartup(wVersionRequested,&wsaData);         if (err!= 0)         {                   returnFALSE;         }         if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)         {                   WSACleanup();                   returnFALSE;         }//……}

//  建立並且初始化通訊端BOOLCmfcAChatDlg::InitSocket(void){         m_socket =WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);         if(INVALID_SOCKET == m_socket)         {                   MessageBox(TEXT("Create socket failed"));                   returnFALSE;         }                 sockaddr_in addrSock;         addrSock.sin_family = AF_INET;         addrSock.sin_port = htons(6000);         addrSock.sin_addr.S_un.S_addr =htonl(INADDR_ANY);          interror = bind(m_socket,(sockaddr*)&addrSock,sizeof(sockaddr));         if(SOCKET_ERROR == error)         {                   MessageBox(TEXT("bind socket failed"));                   returnFALSE;         }          error =WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ);         if(SOCKET_ERROR == error)         {                   MessageBox(TEXT("register network event failed"));                   returnFALSE;         }          returnTRUE;}

//接受訊息響應函數fx_msg LRESULTCmfcAChatDlg::OnSock(WPARAM wParam, LPARAM lParam){         switch(LOWORD(lParam))         {         caseFD_READ:                   WSABUF wsaBuf;                   wsaBuf.buf = new char[200];                   wsaBuf.len = 200;                   DWORD dwRead;                   DWORD dwFlag = 0;                   sockaddr_in addrFrom;                   intlen = sizeof(sockaddr);                   CString str;                   CString strTemp;                   if(SOCKET_ERROR ==WSARecvFrom(m_socket,&wsaBuf,1,&dwRead,&dwFlag,(sockaddr*)&addrFrom,&len,NULL,NULL))                   {                            MessageBox( TEXT("receive  datafailed") );                            delete[] wsaBuf.buf;                            wsaBuf.buf = NULL;                            return 0;                   }                   str.Format(TEXT("%s say :%s"),inet_ntoa(addrFrom.sin_addr),wsaBuf.buf);                   str += TEXT("\r\n");                   GetDlgItemText(IDC_EDIT_RECV,strTemp);                   strTemp += str;                   SetDlgItemText(IDC_EDIT_RECV,strTemp);                   delete[]wsaBuf.buf;                   break;         }         return0;}

//發送訊息void CmfcAChatDlg::OnBnClickedBtnSend(){         // TODO: 在此添加控制項通知處理常式代碼         DWORD dwIP;         CString strSend;         WSABUF wsaBuf;         DWORD dwSend;         intlen;         sockaddr_in addrTo;         ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1) )->GetAddress(dwIP);         addrTo.sin_addr.S_un.S_addr =htonl(dwIP);         addrTo.sin_family = AF_INET;         addrTo.sin_port = htons(6000);                 GetDlgItemText(IDC_EDIT_SEND,strSend);         len = strSend.GetLength();         wsaBuf.buf = strSend.GetBuffer(len);         wsaBuf.len = len + 1;          if(SOCKET_ERROR == WSASendTo(m_socket,&wsaBuf,1,&dwSend,0,(sockaddr*)&addrTo,sizeof(sockaddr),NULL,NULL) )         {                   MessageBox(TEXT("Send message failed") );                   return;         }         SetDlgItemText(IDC_EDIT_SEND,TEXT(""));}

程式的運行結果


基於訊息的非同步通訊端

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.