完成端口模型服务端

windows  完成端口模型服务端

#include<iostream>
#include<winsock2.h>
#pragma comment(lib,"WS2_32.lib")
using namespace std;
const int ServerPort=4399;
const int MSGSIZE=1024;
typedef enum
{
 RECV_POST,
 SEND_POST
}OPERATION_TYPE;
typedef struct 
{
 WSAOVERLAPPED wsaOverlapped;
 WSABUF wsaBuffer;
 char dataBuffer[MSGSIZE];
 DWORD recvedDataSize;
 DWORD flags;
 OPERATION_TYPE operationType;
}COM_IO_OPERATION_DATA,*PIO_OPERATION_DATA;
typedef struct _completionKey
{
   SOCKET sock;
   SOCKADDR_IN sockAddr;
}COMPLETION_KEY,*PCOMPLITON_KEY;
int LoadSocketLib()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 
 wVersionRequested = MAKEWORD( 2, 2 );
 
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {                       
  return -1;
 }
 if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
  WSACleanup( );
  return -1; 
 }
 return 0;
}
DWORD WINAPI HandleThread(LPVOID completionPortID);
BOOL AsyncRecvData(SOCKET clientSOCK);
int main()
{
 system("color 2f");
    //加载套接字库
 if(LoadSocketLib()!=0)
 {
  cout<<"Load winsock failed"<<endl;
        return -1;
 }
 //创建完成端口
    HANDLE completionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
 if(completionPort==NULL)
 {
  cout<<"创建完成端口失败"<<endl;
  return -1;
 }
 SYSTEM_INFO systemInfo;
 GetSystemInfo(&systemInfo);
 DWORD dw_ThreadId;//线程ID
 //创建线程池
 for(int i=0;i<systemInfo.dwNumberOfProcessors;i++)
 {
  CreateThread(NULL,0,HandleThread,completionPort,0,&dw_ThreadId);
 }
    //创建套接字、绑定、设为监听状态
 SOCKET serverSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 if(serverSock==INVALID_SOCKET)
 {
  cout<<"create socket failed"<<endl;
  return -1;
 }
 SOCKADDR_IN serverAddr;
 serverAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 serverAddr.sin_family=AF_INET;
 serverAddr.sin_port=htons(ServerPort);
 if(SOCKET_ERROR==bind(serverSock,(SOCKADDR*)&serverAddr,sizeof(SOCKADDR_IN)))
 {
  cout<<"binding failed"<<endl;
  return -1;
 }
 if(SOCKET_ERROR==listen(serverSock,5))
 {
  cout<<"listen failed"<<endl;
  return -1;
 }
 //接受客户端连接请求,并关联到完成端口
 SOCKADDR_IN clientAddr;
 int addrSize=sizeof(SOCKADDR_IN);
// PIO_OPERATION_DATA lpper_IO_Data=NULL;
 cout<<"/t/t/t"<<"...Server begin..."<<endl;
 PCOMPLITON_KEY  pCompletion=NULL;
 while(1)
 {
  SOCKET clientSock=accept(serverSock,(SOCKADDR*)&clientAddr,&addrSize);
  if(clientSock==INVALID_SOCKET)
  {
   closesocket(clientSock);
   continue;
  }
  //pCompletion=(PCOMPLITON_KEY)malloc(sizeof(COMPLETION_KEY));
     // pCompletion->sock=clientSock;
  //pCompletion->sockAddr=clientAddr;
  cout<<"the client addr is..."<<inet_ntoa(clientAddr.sin_addr)<<"/t"<<ntohs(clientAddr.sin_port)<<endl;
  if(NULL==CreateIoCompletionPort((HANDLE)clientSock,completionPort,/*(DWORD)pCompletion*/(DWORD)clientSock,0))
  {
   cout<<"套接字关联失败"<<endl;
   closesocket(clientSock);
   continue;
  }
  AsyncRecvData(clientSock);//发起异步接受操作
 }
    PostQueuedCompletionStatus(completionPort,0xFFFFFFFF,0,NULL);
 CloseHandle(completionPort);
 closesocket(serverSock);
    WSACleanup();
 return 0;
}
BOOL AsyncRecvData(SOCKET clientSock)
{
 PIO_OPERATION_DATA lpper_IO_Data=NULL;
 lpper_IO_Data=(PIO_OPERATION_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PIO_OPERATION_DATA));//从堆中分配内存块给关联结构体
    if(lpper_IO_Data==NULL)
 {
  cout<<"allocate failed"<<endl;
  closesocket(clientSock);
  //continue;
  return false;
 }
 ZeroMemory(&lpper_IO_Data->wsaOverlapped,sizeof(lpper_IO_Data->wsaOverlapped));
 lpper_IO_Data->wsaBuffer.len=MSGSIZE;
 lpper_IO_Data->wsaBuffer.buf=lpper_IO_Data->dataBuffer;
 lpper_IO_Data->operationType=RECV_POST;
 //异步调用,因此当服务器刚开启的时候第一次激发异步接受Recv会失败,
    if(SOCKET_ERROR==WSARecv(clientSock,&(lpper_IO_Data->wsaBuffer),1,&lpper_IO_Data->recvedDataSize,&lpper_IO_Data->flags,&lpper_IO_Data->wsaOverlapped,NULL))
 {  
 
  if(WSAGetLastError()!=ERROR_IO_PENDING)
  {
   cout<<"WSARecv 函数调用失败"<<WSAGetLastError<<endl;//71A23CCE
   closesocket(clientSock);
   
  }
 }
 return true;
}
DWORD WINAPI HandleThread(LPVOID completionPortID)
{
    HANDLE completionPort=(HANDLE)completionPortID;
 DWORD dwBytesTransferred;
 SOCKET clientSock;
 PIO_OPERATION_DATA lp_IO_Data=NULL;
    //从队列中取出活跃套接字
 GetQueuedCompletionStatus(completionPort,&dwBytesTransferred,(unsigned long*)&clientSock,(LPWSAOVERLAPPED*)&lp_IO_Data,INFINITE);
    
 if(dwBytesTransferred==0xFFFFFFFF)
 {//没有活跃套接字
  return 0;
 }
 if(lp_IO_Data->operationType==RECV_POST)
 {
  if(dwBytesTransferred==0)
  {//客户端关闭
   cout<<"客户端关闭"<<endl;
   closesocket(clientSock);
   HeapFree(GetProcessHeap(),0,lp_IO_Data);
  }
  else
  {//处理客户端请求
     lp_IO_Data->dataBuffer[dwBytesTransferred]='/0';
           //send(clientSock,lp_IO_Data->dataBuffer,dwBytesTransferred,0);
     WSASend(clientSock,&lp_IO_Data->wsaBuffer,1,&lp_IO_Data->recvedDataSize,lp_IO_Data->flags,&lp_IO_Data->wsaOverlapped,NULL);
     memset(lp_IO_Data,0,sizeof(COM_IO_OPERATION_DATA));
     lp_IO_Data->wsaBuffer.buf=lp_IO_Data->dataBuffer;
     lp_IO_Data->wsaBuffer.len=MSGSIZE;
     lp_IO_Data->operationType=RECV_POST;
     WSARecv(clientSock,&lp_IO_Data->wsaBuffer,1,&lp_IO_Data->recvedDataSize,&lp_IO_Data->flags,&lp_IO_Data->wsaOverlapped,NULL);
  }
 }
 return 0;
}


你可能感兴趣的:(IO,struct,socket,null,winapi)