iocps.cpp
来自「提供加密的c/s 聊天程序。用到对称加密算法和非对称加密算法」· C++ 代码 · 共 277 行
CPP
277 行
// IOCPS.cpp: implementation of the IOCPS class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IOCPS.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "mswsock.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IOCPS::IOCPS()
{
m_bOneIPPerConnection=FALSE;
m_bShutDown=FALSE;
WSADATA wsaData;
m_iWSAInitResult=WSAStartup(MAKEWORD(2,2), &wsaData);
m_socListen=NULL;
m_pListenThread=NULL;
m_iMaxNumberOfFreeContext=2;
m_bAcceptConnections=TRUE;
m_bServerStarted=FALSE;
m_iMaxNumConnections=1201;
m_bAcceptJobs=TRUE;
m_nOfWorkers=2;
m_nPortNumber=999;
m_sServerVersion=IOCPSERVERVERSION;
m_NumberOfActiveConnections=0;
m_bSendInOrder=FALSE;
m_bReadInOrder=FALSE;
m_iNumberOfPendlingReads=3;
}
IOCPS::~IOCPS()
{
ShutDown();
if(m_iWSAInitResult == NO_ERROR)
WSACleanup();
}
/*
* Start the Client/Server.
*
*
*/
BOOL IOCPS::Start(int nPort,int iMaxNumConnections,int iMaxIOWorkers,int nOfWorkers,int iMaxNumberOfFreeBuffer,int iMaxNumberOfFreeContext, BOOL bOrderedSend, BOOL bOrderedRead, int iNumberOfPendlingReads)
{
m_iMaxNumberOfFreeBuffer=iMaxNumberOfFreeBuffer;
m_iMaxNumConnections=iMaxNumConnections;
m_nPortNumber=nPort;
m_iMaxIOWorkers=iMaxIOWorkers;
m_nOfWorkers=nOfWorkers;
m_iMaxNumberOfFreeContext=iMaxNumberOfFreeContext;
m_bShutDown=FALSE;
m_bReadInOrder=bOrderedRead;
m_bSendInOrder=bOrderedSend;
m_iNumberOfPendlingReads=iNumberOfPendlingReads;
return Startup();
}
BOOL IOCPS::Startup()
{
// Some special cleanup
#if defined SIMPLESECURITY
m_OneIPPerConnectionList.RemoveAll();
m_BanIPList.RemoveAll();
#endif
CString msg;
AppendLog(m_sServerVersion);
AppendLog("---------------------------------");
AppendLog("Starting system..");
m_NumberOfActiveConnections=0;
if ( m_iWSAInitResult != NO_ERROR )
{
AppendLog("Error at WSAStartup, Winsock 2.0 is not supported. Supported only in WinXP, Win2k and WinNT");
return FALSE;
}else
{
AppendLog("Winsock 2.0 successfully loaded.");
}
BOOL bRet=TRUE;
m_bAcceptConnections=TRUE;
if ( !m_bServerStarted )
{
m_bShutDown=FALSE;
/*
* When using multiple pendling reads (eg m_iNumberOfPendlingReads>1)
* with multiple IOworkers (eg m_iMaxIOWorkers>1), the order of the
* packages are broken, because of IOCP internal design, Furthermore there is no
* Performance gain to have multiple pendling reads if we use more than one IO-worker.
* The throughput is going upp because of serveral pendling reads, but is going down because of
* the ordering part.
*/
if ( m_iMaxIOWorkers>1 ) // we have some sort of bugg somewhere..
m_iNumberOfPendlingReads=1;
if(m_iNumberOfPendlingReads<=0)
m_iNumberOfPendlingReads=1;
msg.Format("Maximum nr of simultaneous connections: %i",m_iMaxNumConnections);
AppendLog(msg);
msg.Format("Number of pendling asynchronous reads: %d",m_iNumberOfPendlingReads);
AppendLog(msg);
// No need to make in order read or write
if ( m_iMaxIOWorkers==1 )
{
m_bReadInOrder=FALSE;
m_bSendInOrder=FALSE;
}
// If we have several Penling Reads and Several IO workers. We must read in order.
if ( m_iNumberOfPendlingReads>1&&m_iMaxIOWorkers>1 )
{
m_bReadInOrder=TRUE;
m_bSendInOrder=TRUE;
}
if ( m_bSendInOrder )
AppendLog("Send ordering initialized. (Decreases the performance by ~3%)");
if ( m_bReadInOrder )
AppendLog("Read ordering initialized.(Decreases the performance by ~3%)");
// The map must be empty
m_ContextMap.RemoveAll();
m_ContextMap.InitHashTable(m_iMaxNumConnections);
// Create the CompletionPort used by IO Worker Threads.
bRet&=CreateCompletionPort();
if( bRet)
{
AppendLog("Completionport successfully created.");
}
// Config the Listner..
if ( m_nPortNumber>0 )
{
bRet&=SetupListner();
if( bRet )
{
AppendLog("Connection listner thread successfully started.");
}
}
// Setup the IOWorkers..
bRet&=SetupIOWorkers();
if ( bRet )
{
msg.Format("Successfully started %i Input Output Worker thread(s).",m_nIOWorkers );
AppendLog(msg);
}
// Start the logical Workers. (SetWorkes can be callen in runtime..).
bRet&=SetWorkers(m_nOfWorkers);
if ( bRet )
{
msg.Format("Successfully started %i logical Worker(s).",m_nOfWorkers);
AppendLog(msg);
}
// Accept incoming Job.
m_bAcceptJobs=TRUE;
m_bServerStarted=TRUE;
}
if ( bRet )
{
if ( m_nPortNumber>0 )
{
msg.Format("Server successfully started.");
AppendLog(msg);
msg.Format("Waiting for clients on adress: %s, port:%i.",GetHostIP(),m_nPortNumber);
AppendLog(msg);
}
else
{
msg.Format("Client successfully started.");
AppendLog(msg);
}
}
return bRet;
}
/*
* Used to determine which connection to accept and deny.
* By using this callback function we can refuse connections
* in lower kernel mode, we don't respond with ACK when the remote
* connection connects with SYN. This means that the remote attacker
* would not know if he/she is blocked or the server is down.
*
*/
#ifdef SIMPLESECURITY
int CALLBACK IOCPS::ConnectAcceptCondition(IN LPWSABUF lpCallerId,
IN LPWSABUF lpCallerData,
IN OUT LPQOS lpSQOS,
IN OUT LPQOS lpGQOS,
IN LPWSABUF lpCalleeId,
OUT LPWSABUF lpCalleeData,
OUT GROUP FAR *g,
IN DWORD dwCallbackData)
{
sockaddr_in* pCaller=(sockaddr_in*)lpCallerId->buf;
sockaddr_in* pCallee=(sockaddr_in*)lpCalleeId->buf;
IOCPS* pThis = reinterpret_cast<IOCPS*>(dwCallbackData);
// Do not take connections from ourself.
/* if ( pCaller->sin_addr.S_un.S_addr == inet_addr("127.0.0.1") )
{
return CF_REJECT;
}
*/
if ( pThis->IsInBannedList(pCaller) || pThis->IsAlreadyConnected(pCaller) )
{
//
// Do not send ACK, the attacker do not know if the server
// exist or not.
//
return CF_REJECT;
}
return CF_ACCEPT;
}
#endif
UINT IOCPS::ListnerThreadProc(LPVOID pParam)
{
IOCPS* pThis = reinterpret_cast<IOCPS*>(pParam);
if ( pThis )
{
while ( !pThis->m_bShutDown )
{
DWORD dwRet;
dwRet = WSAWaitForMultipleEvents(1,
&pThis->m_hEvent,
FALSE,
100,
FALSE);
if(pThis->m_bShutDown)
break;
// Om Det inte h鋘de n錱ot hoppa upp s
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?