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 + -
显示快捷键?