重叠I/O模型实例

来源:互联网 发布:评上院士 知乎 编辑:程序博客网 时间:2024/05/01 02:21
重叠I/O模型实例

 

#include <winsock2.h>
#include <mswsock.h>
#include <iostream.h>
#include <conio.h>

#pragma comment(lib, "ws2_32.lib")

#define    BUFFER_SIZE           4096

SOCKET Sockets[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT Events[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED Overlappeds[WSA_MAXIMUM_WAIT_EVENTS];
char sBuffer[WSA_MAXIMUM_WAIT_EVENTS][BUFFER_SIZE];

SOCKET Listen;
DWORD dwTotal = 0;
volatile long dwClients = 0;
HANDLE hThread;

DWORD GetInvalidIndex(); 
DWORD WINAPI ThreadAccept(LPVOID lpParam);
DWORD  WINAPI  WorkerThread(LPVOID  lpParam);

char sendBuffer[] = "/t Welcome to Overlapped IO Module server/r/n";

void main()
{
 WSADATA wsaData;

 int nRet;
 
 nRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
 if(nRet != 0)
 {
  cout <<"WSAStartup Failed: " <<WSAGetLastError() <<endl;
  return;
 }

 Listen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
 
    if (INVALID_SOCKET == Listen)
    {
  cout <<"WSASocket Failed: " <<WSAGetLastError() <<endl;
        WSACleanup();
        return;
    }
   
    SOCKADDR_IN inAddr;
   
    inAddr.sin_family = AF_INET;
 inAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 inAddr.sin_port = htons(5150);  

    nRet = bind(Listen, (PSOCKADDR)&inAddr, sizeof(inAddr));

    if (SOCKET_ERROR == nRet)
    {
  closesocket(Listen);
  cout <<"bind Failed: " <<WSAGetLastError() <<endl;
  WSACleanup();
        return;
    } 
 
 nRet = listen(Listen, 20);
 
    if (SOCKET_ERROR == nRet)
    {
  closesocket(Listen);
  cout <<"listen Failed: " <<WSAGetLastError() <<endl;
        WSACleanup();
        return;
    } 
   
    for(int i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++)
 {
  Sockets[i] = INVALID_SOCKET;
  Events[i] = WSA_INVALID_EVENT;
  ZeroMemory(&(Overlappeds[i]), sizeof(WSAOVERLAPPED));
  ZeroMemory(&sBuffer[i], BUFFER_SIZE);
 }
 
 hThread = CreateThread(NULL, 0, ThreadAccept, NULL, 0, NULL);
 if(NULL == hThread)
 {
  closesocket(Listen);
  cout <<"CreateThread Failed: " <<GetLastError() <<endl;
        WSACleanup();
        return;
    }
    CloseHandle(hThread);
   
    hThread = CreateThread(NULL, 0, WorkerThread, NULL, CREATE_SUSPENDED, NULL);
 if(NULL == hThread)
 {
  closesocket(Listen);
  cout <<"CreateThread Failed: " <<GetLastError() <<endl;
        WSACleanup();
        return;
    }
 
    cout <<"Enter 'q' to exit: " <<endl;
    while(getch() != 'q');
    closesocket(Listen);
    WSACleanup();
    CloseHandle(hThread);
 cout <<"Main thread will exit " <<endl;
 getch();
}

DWORD GetInvalidIndex()
{
 for(int i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++)
 {
  if(Sockets[i] == INVALID_SOCKET)
   return i;
 }
 return -1;
}

DWORD WINAPI ThreadAccept(LPVOID lpParam)
{
 SOCKET client;
 int nRet;
 WSAEVENT hEvent, Temp;
 WSABUF  wsaBuf;
 DWORD dwRecv;
 DWORD dwSend;
 DWORD dwFlag;
 DWORD dwIndex = -1;

 while(true)
 {
  client = WSAAccept(Listen, NULL, NULL, NULL, 0);
  
  if(client == INVALID_SOCKET)
  {
   cout <<"WSAAccept Failed: " <<WSAGetLastError() <<endl;
   cout <<"ThreadAccept thread exit " <<endl;
         return 0;
        }
  if(dwTotal >= WSA_MAXIMUM_WAIT_EVENTS)
  {
   dwIndex = GetInvalidIndex();
   if(-1 == dwIndex)
   {
          cout <<"Too many connections " <<endl;
          closesocket(client);
          continue;
   }
  }
  else
  {
   dwIndex = dwTotal;
  }
       
  hEvent = WSACreateEvent();
  if(WSA_INVALID_EVENT == hEvent)
  {
   cout <<"WSACreateEvent Failed: " <<WSAGetLastError() <<endl;
   closesocket(client);
         return 0;
  }
  
  Sockets[dwIndex] = client;
  Temp = Events[dwIndex];
  Events[dwIndex] = hEvent;
  if(WSA_INVALID_EVENT != Temp)
  {
   WSACloseEvent(Temp);
  }

  ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
  ZeroMemory(&sBuffer[dwIndex], BUFFER_SIZE);
  Overlappeds[dwIndex].hEvent = hEvent;
  wsaBuf.buf = sBuffer[dwIndex];
  wsaBuf.len = BUFFER_SIZE;
  dwRecv = 0;
  dwFlag = 0;

  nRet = WSARecv(client, &wsaBuf, 1, &dwRecv,  &dwFlag, &(Overlappeds[dwIndex]), NULL);
  if(SOCKET_ERROR == nRet)
  {
   if(ERROR_IO_PENDING != WSAGetLastError())
   {
    cout <<"WSARecv Failed: " <<WSAGetLastError() <<endl;
    closesocket(client);
    Sockets[dwIndex] = INVALID_SOCKET;
    ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
    ZeroMemory(&(sBuffer[dwIndex]), BUFFER_SIZE);
    continue;
   }
  }
  
  ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
  wsaBuf.buf = sendBuffer;
  wsaBuf.len = strlen(sendBuffer);
  dwSend = 0;
  dwFlag = 0;
  
  nRet = WSASend(client, &wsaBuf, 1, &dwSend,  dwFlag, &(Overlappeds[dwIndex]), NULL);
  if(SOCKET_ERROR == nRet)
  {
   if(ERROR_IO_PENDING != WSAGetLastError())
   {
    cout <<"WSASend Failed: " <<WSAGetLastError() <<endl;
    closesocket(client);
    Sockets[dwIndex] = INVALID_SOCKET;
    ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
    ZeroMemory(&(sBuffer[dwIndex]), BUFFER_SIZE);
    continue;
   }
  }
  
  if(dwTotal < WSA_MAXIMUM_WAIT_EVENTS) dwTotal++;
  InterlockedIncrement(&dwClients);
  if(dwClients == 1) ResumeThread(hThread);
  cout <<"Client connected with socket: " <<client <<"  Total = " <<dwClients <<endl;
  cout <<"Send: " <<wsaBuf.buf <<endl;
 }
}

DWORD  WINAPI  WorkerThread(LPVOID  lpParam) 

    DWORD  dwEvent;
 DWORD  Index;
 WSABUF  wsaBuf;
 DWORD dwRecv;
 DWORD dwSend;
 DWORD dwFlag;
 int     nRet;
 //WSAOVERLAPPED ol;

 while(TRUE) 
 { 
  dwEvent  =  WSAWaitForMultipleEvents(dwTotal,  Events,  FALSE,  10/*WSA_INFINITE*/,  FALSE); 
  
  if(WSA_WAIT_TIMEOUT  == dwEvent) 
  { 
   continue;
  } 
  
  if(WSA_WAIT_FAILED  == dwEvent) 
  { 
    cout <<"WSAWaitForMultipleEvents Failed: " <<WSAGetLastError() <<endl;
    return 0; 
  } 
  
  Index =  dwEvent - WSA_WAIT_EVENT_0;
  WSAResetEvent(Events[Index]); 
  
  DWORD dwBytes = 0;
  DWORD dwFlags = 0;
  WSAGetOverlappedResult(Sockets[Index], &(Overlappeds[Index]), &dwBytes, FALSE, &dwFlags);
  
  if(dwBytes == 0)
  {
   cout <<"Client disconnected: " <<Sockets[Index] <<endl;
   ZeroMemory(&(Overlappeds[Index]), sizeof(WSAOVERLAPPED));
   ZeroMemory(&(sBuffer[Index]), BUFFER_SIZE);
   closesocket(Sockets[Index]);
   Sockets[Index] = INVALID_SOCKET;
   InterlockedDecrement(&dwClients);
   if(dwClients == 0) SuspendThread(hThread);
   continue;
  }

  cout<<"Recv: " <<sBuffer[Index] <<endl;
  /*
  ZeroMemory(&ol, sizeof(WSAOVERLAPPED));
  wsaBuf.buf = sBuffer[Index];
  wsaBuf.len = BUFFER_SIZE;
  dwRecv = 0;
  dwSend = 0;
  dwFlag = 0;
  
  nRet = WSASend(Sockets[Index], &wsaBuf, 1, &dwSend, dwFlag, &ol, NULL);
  if(SOCKET_ERROR == nRet)
  {
   if(ERROR_IO_PENDING != WSAGetLastError())
   {
    cout <<"WSARecv Failed: " <<WSAGetLastError() <<endl;
    closesocket(Sockets[Index]);
    Sockets[Index] = INVALID_SOCKET;
    continue;
   }
  }
  */
  ZeroMemory(&(Overlappeds[Index]), sizeof(WSAOVERLAPPED));
  ZeroMemory(&sBuffer[Index], BUFFER_SIZE);
  Overlappeds[Index].hEvent = Events[Index];
  wsaBuf.buf = sBuffer[Index];
  wsaBuf.len = BUFFER_SIZE;
  dwRecv = 0;
  dwSend = 0;
  dwFlag = 0;

  nRet = WSARecv(Sockets[Index], &wsaBuf, 1, &dwRecv,  &dwFlag, &(Overlappeds[Index]), NULL);
  if(SOCKET_ERROR == nRet)
  {
   if(ERROR_IO_PENDING != WSAGetLastError())
   {
    cout <<"WSARecv Failed: " <<WSAGetLastError() <<endl;
    ZeroMemory(&(Overlappeds[Index]), sizeof(WSAOVERLAPPED));
    ZeroMemory(&(sBuffer[Index]), BUFFER_SIZE);
    closesocket(Sockets[Index]);
    Sockets[Index] = INVALID_SOCKET;
    InterlockedDecrement(&dwClients); 
    if(dwClients == 0) SuspendThread(hThread);   
    continue;
   }
  }
 }