📄 iocp_class.cpp
字号:
//---------------------------------------------------------------------------
#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 + -