MFC_IO模型_异步选择模型WSAAsyncSelect
先来说下什么是异步WSAAsyncSelect模型,异步WSAAsyncSelect模型说白了,就是让系统帮咱们去监听咱们服务器上的一个socket
系统会帮我们监听客户端的连接,客户端的断开,客户端的发送数据,等等,
一般,这种模型适用与窗口模型,先来讲讲他如何使用:
1.在创建完窗口的时候,顺便把socket也一起创建了吧,在把咱们的socket交给系统处理(让他我们监听咱们socket的消息,比如客户端连接,断开这些啊,就不用咱们人为的去判断了)
2.重写消息函数,也就是窗口回调函数,里面判断message的消息是否是咱们自定义的消息,然后在判断处理,
3.重写消息函数,拦截WM_DESTROY 消息,对咱们服务端的socket进行关闭和清理socket网络环境
下面看实例:
void Cselect服务端Dlg::OnBnClickedButton1() { WSADATA wsaData; int iaddrSize = sizeof(SOCKADDR_IN); DWORD dwThreadId; // Initialize Windows socket library //装载套接字库 WSAStartup(0x0202, &wsaData); // Create listening socket //创建套接字 sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Bind //绑定 CString ip; this->GetDlgItemText(IDC_EDIT5,ip); USES_CONVERSION; local.sin_addr.S_un.S_addr = inet_addr(W2A(ip.GetBuffer())); ip.ReleaseBuffer(); local.sin_family = AF_INET; this->GetDlgItemText(IDC_EDIT2,ip); local.sin_port = htons(_tstoi(ip.GetBuffer())); ip.ReleaseBuffer(); bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)); // Listen //监听 listen(sListen, 1000); AfxMessageBox(_T("监听成功")); iAddrSize = sizeof(SOCKADDR_IN); WSAAsyncSelect(sListen,this->GetSafeHwnd() , WM_SOCKET, FD_ACCEPT);//第一个参数为需要监听的socket,第二个为窗口句柄,第三个是咱们定义的消息类型,第四个为感兴趣的东西 } LRESULT Cselect服务端Dlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch(message){ case WM_DESTROY: closesocket(sListen);//这个就是关闭socket了撒 WSACleanup();//清理环境,这个就不用说了吧? PostQuitMessage(0);//给系统发送一个消息,就是关闭窗体,也可以重写窗口的destory方法,也可以拦截这个消息,其实默认的destory方法里面就是给窗口发送了一个postmessage消息 return 0; case WM_SOCKET://我们的消息来了吧? if (WSAGETSELECTERROR(lParam))//判断是否socket有异常,有异常还搞个P啊,直接关闭socket { closesocket(wParam);//wParam其实就是客户端的socket break; } switch (WSAGETSELECTEVENT(lParam))//WSAGETSELECTEVENT其实就是一个宏,记住他可以判断socket是什么消息就好了 { case FD_ACCEPT://如果有客户端连接到来的话 // Accept a connection from client sClient = accept(wParam, (struct sockaddr *)&client, &iAddrSize);//咱们就接受他,sClient就是咱们客户端,wParam就是咱们的服务端 // Associate client socket with FD_READ and FD_CLOSE event WSAAsyncSelect(sClient, this->GetSafeHwnd(), WM_SOCKET, FD_READ | FD_CLOSE);//加入到异步选择的容器中,系统自动帮我们管理 break; case FD_READ: char buff[1024]; ret = recv(wParam, buff, sizeof(buff), 0);//这时候wParam就是客户端了 if (ret == 0 || ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET) { closesocket(wParam); } else { buff[ret] = '\0'; send(wParam, buff, strlen(buff)*sizeof(char), 0); } break; case FD_CLOSE: closesocket(wParam);//如果是客户端关闭的话 break; } } return CDialog::WindowProc(message, wParam, lParam); }
在给大家说一个小技巧,如何停止系统对咱们服务端上socket的监听呢?
WSAAsyncSelect(sListen,0 ,0);
把监听的窗口句柄改为0就好了

浙公网安备 33010602011771号