⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iocp_class.cpp

📁 一个完成端口的框架程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------


#pragma hdrstop

#include "IOCP_Class.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)
//---------------------------------------------------------------------------
/*For Class*/
//构造函数
//初始化前置作业参数
__fastcall TtcpIOCP::TtcpIOCP(void)/*constructor*/
{
   SYSTEM_INFO sysInfo;
   OSVERSIONINFO osv;
   osv.dwOSVersionInfoSize=sizeof(osv);
   if(GetVersionEx(&osv))
      FWinver=osv.dwMajorVersion<<8|osv.dwMinorVersion;
   else
      FWinver=0x400;
  MEMORYSTATUSEX statex;

  statex.dwLength = sizeof (statex);
   
  GlobalMemoryStatusEx (&statex);

   /*For Client(s) */
   //FMaxConnections=65535;
   //最大用户连接数(其实该值应当与当前可用物理内存总量相挂勾
   //最大连接数=(当前可用物理内存量-预留16MB)/每连接初始内存分配量
   FMaxConnections=(statex.ullAvailPhys-1024ULL*1024*16/*预留16MB*/)/
                   (sizeof(CONN_CTX)+sizeof(OVERLAPPEDEX));
   //communications
   FConnectionList.clear();
   //recycle for Connections
   FrecycleConnectionList.clear();

   /*For working Threads*/
   //Working threads
   FThreadList.clear();   //总线程列表
   FThreadIDList.clear();//

   /*For IOCP*/
   //完成端口句柄初始化
   FHandle=NULL;
   //前置作业状态标示位初始化
   FIOCPInvalid=false;
   //定时器时脉计数
   TimedCounter=0;
   FTimeOut=30;//默认连接的超时时间为30sec

   /*For Server Thread*/
   //默认端口33333
   FPort=33333;
   //默认绑定本地所有地址
   memset(FBindAddress,0,16);
   //初始化监听Socket
   FListenSock=INVALID_SOCKET;
   //初始化服务状态
   FRunningState=LS_CLOSED;
   //初始化服务状态预设值
   FTuningListenState=LS_CLOSED;
   //初始化监听线程句柄值
   FListenThread=NULL;

   /*For Purifier Thread*/
   //初始化时脉ID
   FPurifierTimer=NULL;

   //初始化各临界区
   InitializeCriticalSection(&conn_CriticalSection);     //有效连接列表临界区
   InitializeCriticalSection(&conn_DUMP_CriticalSection);//用户连接回收列表临界区

   /*For working Threads*/
   InitializeCriticalSection(&thread_CriticalSection);     //有效线程列表临办区
   //初始化活动(可接受新用户通知消息的)线程计数
   FActiveThreadCount=0;

   //取系统信息,用以获取CPU的数量,多核CPU算多个CPU
   GetSystemInfo(&sysInfo);
   //保存CPU数量
   FCPUCount=sysInfo.dwNumberOfProcessors;
#ifdef __DEBUG
   //预置回显(Echo)服务为不可用
   FEchoServer=false;
#endif
   //置期望同步工作线程数为CPU数量*2+1
   FExpectThreadCount=FCPUCount*2+1;
   if(osv.dwPlatformId<VER_PLATFORM_WIN32_NT)
   {
      MessageBox(GetActiveWindow(),
                 "I/O Completion Port Technology is Supportless with Current Platform!\r\n\r\nRunning under NT Technology Platform Please!",
                 "Supportless Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
   }
   EventArray[0]=NULL;
   EventArray[1]=NULL;
   //启动前置作业条件例程
   IOCPInitialize();
}

//析构函数
//清理和释放资源
__fastcall TtcpIOCP::~TtcpIOCP(void)/*destructor*/
{
   //先停止接收新的连接
   DestroyListenThread();
   //关闭所有连接
   CleanConnections();
   //停止所有工作线程
   CleanThreadList();
   //关闭监听Socket
   DestroyListenSock();
   //置关闭状态
   FTuningListenState=LS_CLOSED;
   //检测是否还有连接存在
   while(Connections)
	  Sleep(1);
   //删除时脉工作线程
   DestroyPurifierTimer();
   SetEvent(EventArray[1]);
   WaitForSingleObject(FPurifierThread,INFINITE);
   CloseHandle(FPurifierThread);
   //释放IOCP和网络资源
   IOCPFinalize();
   //删除所有临界区
   DeleteCriticalSection(&thread_CriticalSection);
   DeleteCriticalSection(&conn_CriticalSection);
   DeleteCriticalSection(&conn_DUMP_CriticalSection);
}

/*For IOCP*/
//Initialize I/O C. P. Handle
//初始化前置条件,网络,完成端口等
bool __fastcall TtcpIOCP::IOCPInitialize()
{
   WSAData wsaData;
   if(FIOCPInvalid)
      return FIOCPInvalid;
   FIOCPInvalid=true;
   if(WSAStartup(WINSOCK_VERSION,&wsaData)!=0)
   {
      MessageBox(GetActiveWindow(),
                 "Can not Initilize Network Component!",
                 "Network Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
      FIOCPInvalid=false;
   }
   EventArray[0]=CreateEvent(NULL,false,true,NULL);
   if(EventArray[0]==NULL)
   {
      FIOCPInvalid=false;
      WSACleanup();
      MessageBox(GetActiveWindow(),
                 "Can not create Event!",
                 "I/O Completion Port Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
   }

   EventArray[1]=CreateEvent(NULL,false,false,NULL);
   if(EventArray[1]==NULL)
   {
      FIOCPInvalid=false;
      WSACleanup();
      MessageBox(GetActiveWindow(),
                 "Can not create Event!",
                 "I/O Completion Port Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
   }
   FHandle=CreateNewIoCompletionPort(0);

   if(NULL==FHandle)
   {
      FIOCPInvalid=false;
      WSACleanup();
      MessageBox(GetActiveWindow(),
                 "Can not create Handle!",
                 "I/O Completion Port Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
   }

   FPurifierThread=(HANDLE)_beginthreadex(NULL,0,PurifierThread,this,CREATE_SUSPENDED,&FPurifierThreadID);
   ResumeThread(FPurifierThread);
   if(!CreatePurifierTimer())
   {
      FIOCPInvalid=false;
      CloseHandle(FHandle);
      WSACleanup();
      MessageBox(GetActiveWindow(),
                 "Can not create Timer!",
                 "Timer Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
   }
   return IOCPInvalid;
}

//Destroy I/O C. P. Handle
//关闭完成端口句柄,释放网络资源
void __fastcall TtcpIOCP::IOCPFinalize(void)
{
   if(!FIOCPInvalid)
      return;
   FIOCPInvalid=false;
   if(EventArray[0]!=NULL)
   {
      CloseHandle(EventArray[0]);
      EventArray[0]=NULL;
   }
   if(EventArray[1]!=NULL)
   {
      CloseHandle(EventArray[1]);
      EventArray[1]=NULL;
   }
   CloseHandle(FHandle);
   WSACleanup();
}

/*For Server Thread*/
//Create Listen Socket
//创建监听Socket
bool __fastcall TtcpIOCP::CreateListenSock(void)
{
   //创建WSA_FLAG_OVERLAPPED属性的套接口

   if(!FIOCPInvalid)
      return false; //前置条件无效
   if(FListenSock!=INVALID_SOCKET)
      return true;//监听Socket未创建
   SOCKET sock=WSASocket(AF_INET,
                         SOCK_STREAM,
                         0,
                         NULL,
                         0,
                         WSA_FLAG_OVERLAPPED);
   if(sock==INVALID_SOCKET)
   {
      char Msg[MAX_PATH];
      memset(Msg,0,MAX_PATH);
      sprintf(Msg,
              "WSASocket Error with Error Code (WSA:%d,Error:%d)!\r\nThread terminate later...",
              WSAGetLastError(),
              GetLastError());
      MessageBox(GetActiveWindow(),
                 Msg,
                 "Socket Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
      return false;//Socket失败
   }

   /*设置地址可重入,即可以几个Socket绑定在同IP:Port*/
   bool bReuseAddr=true;
   if(setsockopt(sock,
                 SOL_SOCKET,
                 SO_REUSEADDR,
                 (char*)&bReuseAddr,
                 sizeof(bReuseAddr)
                )==SOCKET_ERROR)
   {
      char Msg[MAX_PATH];
      memset(Msg,0,MAX_PATH);
      sprintf(Msg,
              "setsockopt[SOL_SOCKET:SO_REUSEADDR] Error with Error Code (WSA:%d,Error:%d)!\r\nThread terminate later...",
              WSAGetLastError(),
              GetLastError());
      closesocket(sock);
      MessageBox(GetActiveWindow(),
                 Msg,
                 "Socket Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
      return false;//设置失败
   }

   /*设置发送缓冲区大小*/
   int BufferSize=MAX_BUF_LEN;

   if(setsockopt(sock,
                 SOL_SOCKET,
                 SO_SNDBUF,
                 (const char*)&BufferSize,
                 sizeof(BufferSize))==SOCKET_ERROR)
   {
      char Msg[MAX_PATH];
      memset(Msg,0,MAX_PATH);
      sprintf(Msg,
              "setsockopt[SOL_SOCKET:SO_SNDBUF:%d] Error with Error Code (WSA:%d,Error:%d)!\r\nThread terminate later...",
              BufferSize,
              WSAGetLastError(),
              GetLastError());
      closesocket(sock);
      MessageBox(GetActiveWindow(),
                 Msg,
                 "Socket Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
      return false;
   }
   /*设置接收缓冲区大小*/
   if(setsockopt(sock,
                 SOL_SOCKET,
                 SO_RCVBUF,
                 (const char*)&BufferSize,
                 sizeof(BufferSize))==SOCKET_ERROR)
   {
      char Msg[MAX_PATH];
      memset(Msg,0,MAX_PATH);
      sprintf(Msg,
              "setsockopt[SOL_SOCKET:SO_RCVBUF:%d] Error with Error Code (WSA:%d,Error:%d)!\r\nThread terminate later...",
              BufferSize,
              WSAGetLastError(),
              GetLastError());
      closesocket(sock);
      MessageBox(GetActiveWindow(),
                 Msg,
                 "Socket Error",
                 MB_OK|MB_ICONERROR|MB_APPLMODAL|MB_SETFOREGROUND|MB_TOPMOST);
      ExitThread(-1);
      return false;
   }

   //绑定端口
   struct sockaddr_in local;
   char BindIP[20];
   memset(&local,0,sizeof(local));
   if((strlen(FBindAddress)>0)&&
      ResolveHost(FBindAddress,BindIP))
      local.sin_addr.s_addr=inet_addr(BindIP);
   else
      local.sin_addr.s_addr=htonl(INADDR_ANY);
   local.sin_family=AF_INET;
   local.sin_port=htons(FPort);
   if(bind(sock,
           (struct sockaddr*)&local,
           sizeof(local))==SOCKET_ERROR)
   {
      char Msg[MAX_PATH];
      memset(Msg,0,MAX_PATH);
      sprintf(Msg,
              "bind Error [Address:%s,Port:%d] \r\nwith Error Code (WSA:%d,Error:%d)!",
              (strlen(FBindAddress)>0?FBindAddress:"Inaddr_Any"),
              FPort,
              BufferSize,
              WSAGetLastError(),
              GetLastError());
      closesocket(sock);
      MessageBox(GetActiveWindow(),
                 Msg,
                 "Socket Error",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -