虽然一心想快点学iocp模型,但是赶脚还是得每个模型都简单的了解一下,再去看那个。。。so。。。
WSAAsyncSelect模型:
windows可以在一个socket上接收以windows消息为基础的网络事件通知.
实现了读写数据的异步通知功能,不过不提供异步的数据传输.
int WSAAsyncSelect参数:1,事件通知所需要的socket 2,网络事件发生时,用于接收消息的窗口句柄 3,网络事件发生时接收的消息。 4,感兴趣的网络事件.
窗口例程:
LRESULT CALLBACK WindowProc(窗口句柄,指定由应用程序定义的消息,指定发生网络事件的socket,xx)
最后一个参数:高位标识可能出现的任何错误, 低位指定已经发生的网络事件。
服务端:
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
#define MAXDATASIZE 100
#define BACKLOG 10
#define WM_SOCKET (WM_USER + 1)
SOCKET Accept;
typedef struct _SOCKET_INFORMATION{
CHAR Buffer[MAXDATASIZE];
WSABUF DataBuf;
SOCKET socket;
_SOCKET_INFORMATION *Next;
}SOCKET_INFORMATION, *LPSOCKET_INFORMATION;
LPSOCKET_INFORMATION SocketInfoList; //链表
char Buf[MAXDATASIZE];
//窗口过程
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CreatSocketInformation(SOCKET s)
{
LPSOCKET_INFORMATION SI;
if ( (SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(LPSOCKET_INFORMATION))) == NULL )
{
printf("GlobalAlloc failed\n");
return;
}
SI->socket = s;
SI->Next = SocketInfoList;
SocketInfoList = SI;
}
LPSOCKET_INFORMATION GetSocketInformation(SOCKET s)
{
SOCKET_INFORMATION *SI = SocketInfoList;
while (SI)
{
if (SI->socket == s)
return SI;
SI = SI->Next;
}
return NULL;
}
//创建用于接收消息的窗口
HWND MakeWorkerWindow(void)
{
WNDCLASS wndclass;
HWND Window;
const wchar_t *WinClass = L"Highmore";
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC)WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = NULL; //包含窗口类对应的窗口例程的实例句柄
wndclass.hIcon = LoadIcon(NULL, IDI_WARNING);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = WinClass;
if (RegisterClass(&wndclass) == 0)
{
printf("register failed\n");
return NULL;
}
if ( (Window = CreateWindow(WinClass, L"haha", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, NULL, NULL, NULL, NULL)) == NULL)
{
printf("create window failed\n");
return NULL;
}
return Window;
}
int main(int argc, char *argv[])
{
MSG msg;
HWND hwnd;
DWORD Ret;
SOCKET sockfd;
struct sockaddr_in my_addr;
if( (hwnd = MakeWorkerWindow()) == NULL)
return 0;
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
WSAAsyncSelect(sockfd, hwnd, WM_SOCKET, FD_ACCEPT);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(9990);
my_addr.sin_addr.S_un.S_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));
listen(sockfd, BACKLOG);
while(Ret = GetMessage(&msg, NULL, 0, 0))
{
if (Ret == -1)
{
printf("getMessage failed\n");
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_SOCKET)
{
if (HIWORD(lParam)) //高位标识可能出现的错误
{
printf("socket failed %d", HIWORD(lParam));
}
else
{
switch (LOWORD(lParam)) //地位指定已经发生的网络事件
{
case FD_ACCEPT:
if ( (Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
{
printf("accept failed\n");
break;
}
CreatSocketInformation(Accept);
WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE);
break;
case FD_READ:
SocketInfoList = GetSocketInformation(wParam);
int rec = recv(SocketInfoList->socket, Buf, MAXDATASIZE, 0);
Buf[rec] = '\0';
if (rec > 0)
{
printf("received %s", Buf);
}
break;
}
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}