WSAAsyncSelect之MFC模型

WSAAsyncSelect模型允许应用程序以Windows消息的方式接收网络事件通知。许多对性能要求不高的网络应用程序都采用WSAAsyncSelect模型,MFC的CSocket类也使用了它。

        WSAAsyncSelect自动把套接字设为非阻塞模式,并且为套接字绑定一个窗口句柄,当有网络事件发生时,便向这个窗口发送消息。

        intWSAAsyncSelect(

        SOCKET s,                  //需要设置的套接字句柄

        HWND  hWnd,     //指定一个窗口句柄, 套接字的通知消息将被发到此窗口中

       u_int    wMsg,     //网络事件到来的ID,可以在WM_USER以上数值中任意指定一个值

       long    IEvent     //指定哪些通知码需要发送

                                 //FD_READ可以读套接字

                                 //FD_WRITE 可以写套接字

                                //FD_ACCEPT 监听套接字有连接接入

                               //FD_CONNET  如果套接字连接对方主机,连接完成后会收到这个通知码

                              //FD_CLOSE 检测到套接字对应的连接被关闭

)

       回传过来的消息类型与注册的wMsg相同,wParam等于套接字句柄,lParam通过WSAGETSELECTEVENT转义后就是FD_READ,FD_WRITE,FD_ACCEPT,FD_CONNET,FD_CLOSE

        代码如下:

        新建一个基于MFC对话框的工程,工程名为test,然后在testDlg.h中定义      

[cpp]  view plain  copy
  1. #include "winsock2.h"  
  2. #pragma comment(lib, "WS2_32")  
  3. #define WM_SOCKET (WM_USER+1)   
同时在该文件中加入一个自定义消息处理函数

[cpp]  view plain  copy
  1. afx_msg LRESULT OnSocketMsg(WPARAM wParam,LPARAM lParam);  
在testDlg.cpp中定义

[cpp]  view plain  copy
  1. ON_MESSAGE(WM_SOCKET,OnSocketMsg)  

在OnInitDialog中加入自己的初始化代码

[cpp]  view plain  copy
  1. // TODO: 在此添加额外的初始化代码  
  2.   
  3.     WSADATA wsaData;  
  4.     WORD sockVersion = MAKEWORD(2, 2);  
  5.     if(WSAStartup(sockVersion, &wsaData) != 0)  
  6.     {  
  7.         return 0;  
  8.     }  
  9.     USHORT nPort=4567;  
  10.     SOCKET s=socket(AF_INET,SOCK_STREAM,0);  
  11.     sockaddr_in sin;  
  12.     sin.sin_family=AF_INET;  
  13.     sin.sin_port=ntohs(nPort);  
  14.     sin.sin_addr.S_un.S_addr=INADDR_ANY;  
  15.     if(bind(s,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)  
  16.     {  
  17.         DWORD error=GetLastError();  
  18.         return TRUE;  
  19.     }  
  20.   
  21.     WSAAsyncSelect(s,m_hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);  
  22.     listen(s,5);  

添加自定义消息函数的处理:

[cpp]  view plain  copy
  1. LRESULT CtestDlg::OnSocketMsg(WPARAM wParam,LPARAM lParam)  
  2. {  
  3.     SOCKET s=wParam;  
  4.     CString strContent;  
  5.     if(WSAGETSELECTERROR(lParam))  
  6.     {  
  7.         closesocket(s);  
  8.         return false;  
  9.     }  
  10.     switch(WSAGETSELECTEVENT(lParam))  
  11.     {  
  12.     case FD_ACCEPT://检测到有套接字连上来  
  13.         {  
  14.             SOCKET client=accept(s,NULL,NULL);  
  15.             WSAAsyncSelect(client,m_hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE);  
  16.             CString strContent;  
  17.             GetDlgItemText(IDC_EDIT1,strContent);  
  18.             if(!strContent.IsEmpty())  
  19.             {  
  20.                 strContent+="\r\n";  
  21.             }             
  22.             strContent+="有客户端连上来了";  
  23.             SetDlgItemText(IDC_EDIT1,strContent);//将内容显示到Edit控件  
  24.         }  
  25.         break;  
  26.     case FD_WRITE:  
  27.         {  
  28.         }  
  29.         break;  
  30.     case FD_READ:  
  31.         {  
  32.             char szText[1024]={0};  
  33.             if(recv(s,szText,1024,0)==-1)  
  34.                 closesocket(s);  
  35.             else  
  36.             {                 
  37.                 GetDlgItemText(IDC_EDIT1,strContent);  
  38.                 if(!strContent.IsEmpty())  
  39.                 {  
  40.                     strContent+="\r\n";  
  41.                 }  
  42.                 CString strTemp;  
  43.                 strTemp.Format("%s",szText);  
  44.                 strContent+=strTemp;  
  45.                 SetDlgItemText(IDC_EDIT1,strContent);//将内容显示到Edit控件中  
  46.             }  
  47.         }  
  48.         break;  
  49.     case FD_CLOSE:  
  50.         {  
  51.             closesocket(s);  
  52.             GetDlgItemText(IDC_EDIT1,strContent);  
  53.             if(!strContent.IsEmpty())  
  54.             {  
  55.                 strContent+="\r\n";  
  56.             }             
  57.             strContent+="有客户端断开了";  
  58.             SetDlgItemText(IDC_EDIT1,strContent);//将内容显示到Edit控件中  
  59.         }  
  60.         break;  
  61.     }  
  62.     return true;  
  63. }  

对WM_DESTROY消息处理,清理套接字库

[cpp]  view plain  copy
  1. void CtestDlg::OnDestroy()  
  2. {  
  3.     CDialog::OnDestroy();  
  4.     WSACleanup();  
  5.     // TODO: 在此处添加消息处理程序代码  
  6. }  


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值