网络编程五种IO模型之WSAEventSelect模型

来源:互联网 发布:网络非法赌博投诉电话 编辑:程序博客网 时间:2024/04/29 06:59
/*client.cpp  */#include <Winsock2.h>#include <stdio.h>#include <conio.h>#include <iostream>#include "Globle.h"#pragma comment(lib, "ws2_32.lib")#defineMAX_THREAD5HANDLE ThreadPool[MAX_THREAD] = {NULL};volatile BOOL bExit = FALSE;void Init(){InitializeCriticalSection(&csGeneralData);InitializeCriticalSection(&csShowMsg);srand(time(0));}void BeforeExit(){DeleteCriticalSection(&csGeneralData);DeleteCriticalSection(&csShowMsg);}DWORD GetSocket(SOCKET &s){DWORD dwCode;char Msg[1024] = "";closesocket(s);s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //建立一个TCP/IP协议的套接字if(s == INVALID_SOCKET){dwCode = WSAGetLastError();sprintf(Msg, "\nCan't create the socket:%d \n", dwCode);ShowMsg(Msg);return dwCode;}return 0;}DWORD DoConnect(SOCKET &s){DWORD dwCode;//char Msg[1024] = "";SOCKADDR_IN server;server.sin_family = AF_INET;server.sin_port = htons(PORT);server.sin_addr.s_addr = inet_addr("127.0.0.1");dwCode = connect(s, (sockaddr*)&server, sizeof(server));return dwCode;}// 处理连接DWORD WINAPI WorkerThread(LPVOID lpParam){char Msg[1024] = "";int iIndex = (int)lpParam;string sThreadName;sprintf(Msg, "WorkerThread %d ", iIndex);sThreadName = Msg;sprintf(Msg, "WorkerThread %d start...\n", iIndex);ShowMsg(Msg);char Buf[BUFFER_SIZE] = "";BOOL bConnect = FALSE;SOCKET s;DWORD dwCode;GetSocket(s);while(!bExit){if(!bConnect){while( (dwCode=DoConnect(s)) != 0 && !bExit){dwCode = WSAGetLastError();sprintf(Msg, "can't connect to the server:%d \n", dwCode);::ShowMsg(sThreadName+Msg);if(dwCode != WSAECONNREFUSED && dwCode !=WSAENETUNREACH && dwCode != WSAETIMEDOUT){GetSocket(s);sprintf(Msg, "create socket %d", s);ShowMsg(sThreadName + Msg);}Sleep(3000);ShowMsg(sThreadName + "connect to the server...");}if(dwCode == 0)bConnect = TRUE;if(bExit)break;}Sleep(2000);// 延时2秒::GetData(Buf);dwCode = ::send(s, Buf, 20, 0);sprintf(Msg, "socket %d sended data to the server:%s", s, Buf);ShowMsg(sThreadName + Msg);if(dwCode == SOCKET_ERROR){dwCode = ::WSAGetLastError();sprintf(Msg, "socket %d can't send data to the server:%d \n", s, dwCode);::ShowMsg(sThreadName + Msg);//if(dwCode == WSAESHUTDOWN || dwCode == WSAECONNABORTED || dwCode == WSAECONNRESET//|| dwCode == WSAENOTSOCK){GetSocket(s);bConnect = FALSE;continue;}}dwCode = ::recv(s, Buf, BUFFER_SIZE, 0);if(dwCode == SOCKET_ERROR){dwCode = ::WSAGetLastError();sprintf(Msg, "socket %d can't receive data from the server:%d \n", s, dwCode);::ShowMsg(sThreadName+Msg);//if(dwCode == WSAESHUTDOWN || dwCode == WSAECONNABORTED || dwCode == WSAECONNRESET//|| dwCode == WSAENOTSOCK){GetSocket(s);bConnect = FALSE;continue;}}sprintf(Msg, "socket %d received data from the server:%s", s, Buf);ShowMsg(sThreadName+Msg);Sleep(500);}closesocket(s);sprintf(Msg, "WorkerThread %d exit...\n", iIndex);ShowMsg(Msg);return 0;}void main(){int i;Init();WSADATA wsaData;DWORD dwCode = WSAStartup(MAKEWORD(2, 2), &wsaData);//初始化WinSockif(dwCode != 0){printf("\nCan't find find a usable WinSock DLL");goto EXIT;}if ( LOBYTE( wsaData.wVersion ) != 2 ||  HIBYTE( wsaData.wVersion ) != 2 ){printf("\nCan't find the socket version required.");goto EXIT;    }for(i = 0; i < MAX_THREAD; i++){HANDLE hThread = ::CreateThread(NULL, NULL, WorkerThread, (LPVOID)i, 0, NULL);ThreadPool[i] = hThread;}ShowMsg("Press 'q' to exit...\n");while(_getch() != 'q' && _getch() != 'Q'){ShowMsg("Press 'q' to exit...\n");}bExit = TRUE;::WaitForMultipleObjects(MAX_THREAD, ThreadPool, TRUE, INFINITE);for(i = 0; i < MAX_THREAD; i++)::CloseHandle(ThreadPool[i]);EXIT:::WSACleanup();BeforeExit();printf("press any key to exit...");getch();    return;}

#include <conio.h>#include <stdio.h>#include <winsock2.h>//#include <mswsock.h>#include "Globle.h"#pragma comment(lib, "ws2_32.lib")#defineMAX_CLIENTFD_SETSIZESOCKET Listen;HANDLE ThreadPool[FD_SETSIZE] = {NULL};SOCKET Client[FD_SETSIZE] = {0};SOCKET Socket[WSA_MAXIMUM_WAIT_EVENTS] = { 0 };WSAEVENT Event[WSA_MAXIMUM_WAIT_EVENTS] = { NULL };DWORD EventTotal = 0;volatile BOOL bExit  = FALSE;static int nThreadCout = 0;void Init(){//InitializeCriticalSection(&csFDRead);InitializeCriticalSection(&csGeneralData);InitializeCriticalSection(&csShowMsg);srand(time(0));}void BeforeExit(){//DeleteCriticalSection(&csFDRead);DeleteCriticalSection(&csGeneralData);DeleteCriticalSection(&csShowMsg);}void CompressArray(DWORD Index){if(Index < 0 || Index > WSA_MAXIMUM_WAIT_EVENTS)return;Socket[Index] = Socket[EventTotal-1];Socket[EventTotal-1] = 0;WSAEVENT hEvent = Event[Index];Event[Index] = Event[EventTotal-1];::WSACloseEvent(hEvent);Event[EventTotal-1] = 0;EventTotal--;}DWORD WINAPI WorkerThread(LPVOID lpParam)  {char Buf[BUFFER_SIZE] = {0};char Msg[1024] = "";ShowMsg("WorkerThread start...");DWORD dwCode;WSANETWORKEVENTS NetWorkEvent;DWORD Index;while(!bExit){Index = ::WSAWaitForMultipleEvents(EventTotal, Event, FALSE, WSA_INFINITE, FALSE);//::WSAResetEvent(Event[Index - WSA_WAIT_EVENT_0]);::WSAEnumNetworkEvents(Socket[Index-WSA_WAIT_EVENT_0],Event[Index-WSA_WAIT_EVENT_0],&NetWorkEvent);sprintf(Msg, "Total clients:%d", EventTotal-1);ShowMsg(Msg);if(NetWorkEvent.lNetworkEvents & FD_ACCEPT){if(NetWorkEvent.iErrorCode[FD_ACCEPT_BIT] != 0){sprintf(Msg, "FD_ACCEPT failed with error %d",NetWorkEvent.iErrorCode[FD_ACCEPT_BIT]);ShowMsg(Msg);continue;}SOCKET Client = accept(Socket[Index - WSA_WAIT_EVENT_0], NULL, NULL);if(EventTotal > WSA_MAXIMUM_WAIT_EVENTS){ShowMsg("Too many connections!");closesocket(Client);continue;}sprintf(Msg, "Socket %d connected...", Client);ShowMsg(Msg);WSAEVENT hEvent = ::WSACreateEvent();::WSAEventSelect(Client, hEvent, FD_READ | FD_WRITE | FD_CLOSE);Socket[EventTotal] = Client;Event[EventTotal] = hEvent;EventTotal++;}if(NetWorkEvent.lNetworkEvents & FD_READ){if(NetWorkEvent.iErrorCode[FD_READ_BIT] != 0){sprintf(Msg, "FD_READ failed with error %d",NetWorkEvent.iErrorCode[FD_READ_BIT]);ShowMsg(Msg);continue;}dwCode = recv(Socket[Index - WSA_WAIT_EVENT_0], Buf, BUFFER_SIZE, 0);if(dwCode == SOCKET_ERROR){sprintf(Msg, "An error occured when reading data from socket %d, error code %d", Socket[Index - WSA_WAIT_EVENT_0], ::WSAGetLastError());ShowMsg(Msg);continue;}Buf[dwCode] = '\0';sprintf(Msg, "Received data from socket %d: %s", Socket[Index - WSA_WAIT_EVENT_0], Buf);ShowMsg(Msg);GetData(Buf);dwCode = send(Socket[Index - WSA_WAIT_EVENT_0], Buf, 21, 0);if(dwCode == SOCKET_ERROR){sprintf(Msg, "An error occured when Sending data to socket %d, error code %d", Socket[Index - WSA_WAIT_EVENT_0], ::WSAGetLastError());ShowMsg(Msg);continue;}sprintf(Msg, "Sended data to socket %d: %s",Socket[Index - WSA_WAIT_EVENT_0], Buf);ShowMsg(Msg);}/* 何时收到 FD_WRITE 消息1、有数据可以发出;   2、如果已完成了对一个非锁定连接调用的处理连接就会成功。FD_WRITE 被定义为当缓存由满->空时触发该事件(连接成功时会有一次,这是例外)   第一次FD_WRITE事件后,你就可以不停地发数据了。如果缓存的数据都被及时发送出去后就不会再有FD_WRITE事件。当发送返回WSAEWOULDBLOCK错误时,停止发送,等待FD_WRITE事件再次触发。*/if(NetWorkEvent.lNetworkEvents & FD_WRITE){if(NetWorkEvent.iErrorCode[FD_WRITE_BIT] != 0){sprintf(Msg, "FD_WRITE failed with socke %d, error code %d",Socket[Index - WSA_WAIT_EVENT_0],NetWorkEvent.iErrorCode[FD_WRITE_BIT]);ShowMsg(Msg);}ShowMsg("--------------------------------------");}if(NetWorkEvent.lNetworkEvents & FD_CLOSE){if(NetWorkEvent.iErrorCode[FD_CLOSE_BIT] != 0){sprintf(Msg, "FD_CLOSE failed with socke %d, error code:%d", Socket[Index - WSA_WAIT_EVENT_0],NetWorkEvent.iErrorCode[FD_CLOSE_BIT]);ShowMsg(Msg);//continue;}sprintf(Msg, "Close socket %d", Socket[Index - WSA_WAIT_EVENT_0]);ShowMsg(Msg);closesocket(Socket[Index - WSA_WAIT_EVENT_0]);CompressArray(Index - WSA_WAIT_EVENT_0);}}ShowMsg("WorkerThread exit...");return 0;}int main(){int i = 0;DWORD dwCode;WSADATA wsaData;HANDLE hThread = NULL;WSAEVENT NewEvent;Init();dwCode = WSAStartup(MAKEWORD(2,2), &wsaData);if(dwCode != 0){printf("\nCan't find find a usable WinSock DLL");goto EXIT;}if ( LOBYTE( wsaData.wVersion ) != 2 ||  HIBYTE( wsaData.wVersion ) != 2 ){printf("\nCan't find the socket version required.");goto EXIT;    }Listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if(Listen == INVALID_SOCKET){cout << "\nCan't create the socket:" << WSAGetLastError() << endl;goto EXIT;}SOCKADDR_IN sockAddr;sockAddr.sin_family = AF_INET;sockAddr.sin_addr.s_addr = ADDR_ANY;sockAddr.sin_port = htons(PORT);dwCode = bind(Listen, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));if(dwCode == SOCKET_ERROR){::closesocket(Listen);cout << "\nCan't bind the socket:" << WSAGetLastError() << endl;goto EXIT;}NewEvent = ::WSACreateEvent();WSAEventSelect(Listen, NewEvent, FD_ACCEPT | FD_CLOSE);Socket[EventTotal] = Listen;Event[EventTotal] = NewEvent;EventTotal++;dwCode = listen(Listen, 20);if(dwCode == SOCKET_ERROR){::closesocket(Listen);cout << "\nCan't listen:" << WSAGetLastError() << endl;goto EXIT;}hThread = ::CreateThread(NULL, NULL, WorkerThread, NULL, 0, NULL);// CREATE_SUSPENDEDThreadPool[nThreadCout++] = hThread;//hThread = ::CreateThread(NULL, NULL, ReadThread, 0, 0, NULL);//ThreadPool[nThreadCout++] = hThread;//hThread = ::CreateThread(NULL, NULL, SendThread, 0, 0, NULL);//ThreadPool[nThreadCout++] = hThread;ShowMsg("Press 'q' to exit...\n");while(_getch() != 'q' && _getch() != 'Q'){ShowMsg("Press 'q' to exit...\n");}bExit = TRUE;::WSASetEvent(Event[0]);for(i = 0; i < EventTotal; i++)// Listen已经包含在其中了closesocket(Socket[i]);for(i = 1; i < EventTotal; i++)WSACloseEvent(Event[i]);//::closesocket(Listen);::WaitForMultipleObjects(nThreadCout, ThreadPool, TRUE, INFINITE);for(i = 0; i < nThreadCout; i++)::CloseHandle(ThreadPool[i]);EXIT:WSACleanup();BeforeExit();printf("\nPress any key to exit...");_getch();return 0;}

原创粉丝点击