WSAAsyncSelect模型分析
#include<winsock2.h> #include<windows.h> #include<stdio.h> #pragma comment (lib,"ws2_32.lib") #define PORT 8888 #define ADDR "127.0.0.1" //char ADDR[15]; #define MSGSIZE 1024 #define WM_SOCKET WM_USER+1 #define serecho "get it" LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow) { //printf("server IP is : "); //gets(ADDR); static TCHAR szAppName[]=L"TCPAsyn server f_ck"; HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style=CS_HREDRAW |CS_VREDRAW; wndclass.lpfnWndProc=WndProc; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hInstance=hInstance; wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName=NULL; wndclass.lpszClassName=szAppName; if(!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("this program requires windows NT"),szAppName,MB_ICONERROR); return 0; } hwnd=CreateWindow( szAppName, TEXT("WHAT A F_CK TCPAsyn TITLE"), WS_OVERLAPPEDWINDOW, 100,100,800,600, NULL,NULL,hInstance,NULL ); ShowWindow(hwnd,iCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) { WSADATA wsadata; SOCKET listensocket,acceptsocket; SOCKADDR_IN seraddr,cliaddr; int nret; int cliaddrsize=sizeof(cliaddr); char szmessage[MSGSIZE]; switch(message) { case WM_CREATE: if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0) { MessageBox(NULL,TEXT("WSAStartup() failed"),TEXT("wrong"),MB_OK); return 0; } if((listensocket=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) { MessageBox(NULL,TEXT("create socket failed "),TEXT("wrong"),MB_OK); WSACleanup(); return 0; } seraddr.sin_family=AF_INET; seraddr.sin_addr.s_addr=inet_addr(ADDR); seraddr.sin_port=htons(PORT); if(bind(listensocket,(SOCKADDR*)&seraddr,sizeof(seraddr))==SOCKET_ERROR) { MessageBox(NULL,TEXT("bind failed"),TEXT("wrong"),MB_OK); closesocket(listensocket); WSACleanup(); return 0; } if(listen(listensocket,5))//无错误返回0,有错返回SOCKET ERROR { MessageBox(NULL,TEXT("listen failed"),TEXT("wrong"),MB_OK); closesocket(listensocket); WSACleanup(); return 0; } if(WSAAsyncSelect(listensocket,hwnd,WM_SOCKET,FD_ACCEPT|FD_READ|FD_WRITE)==SOCKET_ERROR)//WM_SOCKET it's here!! { MessageBox(NULL,TEXT("WSAAsyncSelect() failed"),TEXT("wrong"),MB_OK); closesocket(listensocket); WSACleanup(); return 0; } return 0; case WM_DESTROY: //closesocket(listensocket); WSACleanup(); PostQuitMessage(0); return 0; case WM_SOCKET: if(WSAGETSELECTERROR(lparam)) { closesocket(wparam); break; } switch(WSAGETSELECTEVENT(lparam)) { case FD_ACCEPT: if((acceptsocket=accept(wparam,(SOCKADDR*)&cliaddr,&cliaddrsize))==SOCKET_ERROR) { MessageBox(NULL,TEXT("accept failed"),TEXT("wrong"),MB_OK); WSACleanup(); return 0; } if(WSAAsyncSelect(acceptsocket,hwnd,WM_SOCKET,FD_READ|FD_CLOSE|FD_WRITE)==SOCKET_ERROR) { MessageBox(NULL,TEXT("WSAAsyncSelect() failed"),TEXT("wrong"),MB_OK); WSACleanup(); return 0; } break; case FD_READ: if((nret=recv(wparam,szmessage,MSGSIZE,0))==SOCKET_ERROR) { closesocket(wparam); } else { send(wparam,serecho,strlen(serecho),0); //szmessage[nret]=''; //send(wparam,szmessage,strlen(szmessage),0); } break; case FD_CLOSE: closesocket(wparam); break; } return 0; } return DefWindowProc(hwnd,message,wparam,lparam); }这是我的TCP服务器端的程序,采用WSAAsyncSelect模型,但是我不明白select模型如何就实现非阻塞通信了?在代码上是怎么体现的?和一个普通的服务器端程序相比又有什么不同?
fdfd
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
非阻塞 只是看用的 套接字对象 类型. 你用阻塞的socket就阻塞, 用设置非阻塞选项的socket 就非阻塞.
select只是搭配非阻塞套接字的 模型而已, 他一次能等待多个套接字. 不等待的套接字模型是不存在, 想想就知道. 你肯定要等网络来数据 是吧. 呵呵.
epoll等待的效率就更高了. iocp则是系统级的线程池回调. 都是搭配非阻塞socket的好模型.