Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
#include "stdafx.h"
|
||||
#include "CompletionHandler.h"
|
||||
|
||||
CCompletionHandler::CCompletionHandler()
|
||||
: m_hIOCP(INVALID_HANDLE_VALUE), m_nThread(0), m_nTimeOutMS(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CCompletionHandler::~CCompletionHandler()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
||||
bool CCompletionHandler::Initialize(unsigned long nThread, unsigned long nTimeOutMS)
|
||||
{
|
||||
if(INVALID_HANDLE_VALUE != m_hIOCP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, nThread);
|
||||
if(0 == m_hIOCP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nThread = nThread;
|
||||
m_nTimeOutMS = nTimeOutMS;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CCompletionHandler::Destroy()
|
||||
{
|
||||
if(INVALID_HANDLE_VALUE != m_hIOCP)
|
||||
{
|
||||
if(!CloseHandle(m_hIOCP))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_hIOCP = INVALID_HANDLE_VALUE;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
#ifndef _CCOMPLETIONHANDLER_H_
|
||||
#define _CCOMPLETIONHANDLER_H_
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CCompletionHandler Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCompletionHandler
|
||||
{
|
||||
private:
|
||||
|
||||
HANDLE m_hIOCP;
|
||||
unsigned long m_nThread;
|
||||
unsigned long m_nTimeOutMS;
|
||||
|
||||
public:
|
||||
|
||||
CCompletionHandler();
|
||||
virtual ~CCompletionHandler();
|
||||
|
||||
bool Initialize(unsigned long nThread = 0, unsigned long nTimeOutMS = INFINITE); // Completion Handler를 초기화한다.
|
||||
bool Destroy(); // Completion Hander를 소멸시킨다.
|
||||
|
||||
bool AttachToHander(HANDLE hAttach, ULONG_PTR pCompletionKey); // Completion Handler에 새 핸들을 추가한다.
|
||||
|
||||
BOOL GetHanderStatus(LPDWORD lpNumOfBytes,
|
||||
PULONG_PTR lpCompletionKey, LPOVERLAPPED *lpOverlapped); // 작업이 끝난 핸들을 얻어 온다. 그동안은 block된다.
|
||||
|
||||
BOOL PostToHandler(unsigned long dwNumOfBytesTransfered,
|
||||
ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped); // Handler에 작업을 강제로 추가한다.
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inline Implementation ------------------------------------------------------
|
||||
|
||||
inline bool CCompletionHandler::AttachToHander(HANDLE hAttach, ULONG_PTR pCompletionKey)
|
||||
{
|
||||
return (0 != CreateIoCompletionPort(hAttach, m_hIOCP, pCompletionKey, m_nThread));
|
||||
}
|
||||
|
||||
|
||||
inline BOOL CCompletionHandler::GetHanderStatus(LPDWORD lpNumOfBytes,
|
||||
PULONG_PTR lpCompletionKey, LPOVERLAPPED *lpOverlapped)
|
||||
{
|
||||
return GetQueuedCompletionStatus(m_hIOCP, lpNumOfBytes, lpCompletionKey, lpOverlapped, m_nTimeOutMS);
|
||||
}
|
||||
|
||||
|
||||
inline BOOL CCompletionHandler::PostToHandler(unsigned long dwNumOfBytesTransfered,
|
||||
ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
return PostQueuedCompletionStatus(m_hIOCP, dwNumOfBytesTransfered, dwCompletionKey, lpOverlapped);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
354
Server/RylServerProject/BaseLibrary/Network/Iocp/IOCPNet.cpp
Normal file
354
Server/RylServerProject/BaseLibrary/Network/Iocp/IOCPNet.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "IOCPNet.h"
|
||||
#include "IOWorker.h"
|
||||
|
||||
#include "CompletionHandler.h"
|
||||
#include "../../Thread/ThreadMgr.h"
|
||||
#include "../../Stream/Buffer/BufferFactory.h"
|
||||
|
||||
|
||||
#include "../Session/Session.h"
|
||||
#include "../Session/SessionMgr.h"
|
||||
#include "../Listener/Listener.h"
|
||||
|
||||
#include "../Dispatch/Dispatch.h"
|
||||
#include "../Winsock/SocketFactory.h"
|
||||
#include "../../Utility/Resource/EnsureCleanup.h"
|
||||
#include "../../Utility/Debug/DebugUtils.h"
|
||||
|
||||
#include "../../Log/ServerLog.h"
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
||||
enum IOCPInternalFlag
|
||||
{
|
||||
INITIALIZED_IOCP = (1 << 0),
|
||||
DESTROYED_IOCP = (1 << 1)
|
||||
};
|
||||
|
||||
|
||||
unsigned long GetOptimalThreadNum()
|
||||
{
|
||||
unsigned long dwThreadCount;
|
||||
SYSTEM_INFO systemInfo;
|
||||
|
||||
GetSystemInfo(&systemInfo);
|
||||
dwThreadCount = systemInfo.dwNumberOfProcessors * 2;
|
||||
|
||||
return dwThreadCount;
|
||||
}
|
||||
|
||||
|
||||
CIOCPNet::CIOCPNet()
|
||||
: m_dwFlags(0),
|
||||
m_lpSocketHandler(new (std::nothrow) CCompletionHandler),
|
||||
m_lpThreadMgr(new (std::nothrow) CThreadMgr),
|
||||
m_lpSessionMgr(new (std::nothrow) CSessionMgr)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
WSAStartup(0x0202, &wsaData);
|
||||
}
|
||||
|
||||
|
||||
CIOCPNet::~CIOCPNet()
|
||||
{
|
||||
Destroy();
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
|
||||
// Desc : 초기화 및 스레드 생성.
|
||||
bool CIOCPNet::Initialize()
|
||||
{
|
||||
{
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
|
||||
// 초기화는 한번만 할 수 있음.
|
||||
if(INITIALIZED_IOCP & m_dwFlags)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dwFlags |= INITIALIZED_IOCP;
|
||||
}
|
||||
|
||||
if(0 == m_lpSocketHandler ||
|
||||
0 == m_lpThreadMgr ||
|
||||
0 == m_lpSessionMgr ||
|
||||
!m_lpSocketHandler->Initialize())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// IOCP 스레드 생성.
|
||||
unsigned long dwThreadNum = GetOptimalThreadNum();
|
||||
while(0 != dwThreadNum--)
|
||||
{
|
||||
if(!m_lpThreadMgr->RegisterAndRun(
|
||||
new (std::nothrow) CIOWorker(*m_lpSocketHandler)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Desc : Listener를 생성한다.
|
||||
bool CIOCPNet::AddListener(CSessionPolicy* lpSessionPolicy,
|
||||
const char* lpListenAddress, unsigned short usPort,
|
||||
unsigned long dwMaxListenPeding,
|
||||
CValidateConnection* lpValidateConnection)
|
||||
{
|
||||
if(0 == lpSessionPolicy || !lpSessionPolicy->IsValid() ||
|
||||
0 == m_lpSocketHandler || 0 == m_lpSessionMgr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CListener* lpListener = new (std::nothrow) CListener(*m_lpSocketHandler,
|
||||
*lpSessionPolicy, *m_lpSessionMgr, lpValidateConnection);
|
||||
|
||||
if(0 == lpListener)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!lpListener->Initialize(lpListenAddress, usPort, dwMaxListenPeding))
|
||||
{
|
||||
delete lpListener;
|
||||
return false;
|
||||
}
|
||||
|
||||
lpSessionPolicy->AddRef();
|
||||
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
m_ListenerList.push_back(lpListener);
|
||||
++m_SessionPolicyMap[lpSessionPolicy];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Desc : 연결 세션을 생성한다.
|
||||
bool CIOCPNet::Connect(CSessionPolicy* lpSessionPolicy,
|
||||
const char* lpConnectAddress, unsigned short usPort)
|
||||
{
|
||||
if(0 == lpSessionPolicy || !lpSessionPolicy->IsValid() ||
|
||||
0 == m_lpSocketHandler || 0 == m_lpSessionMgr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SOCKET hConnectedSocket = lpSessionPolicy->GetSocketFactory().CreateConnectedSocket(lpConnectAddress, usPort);
|
||||
if(INVALID_SOCKET == hConnectedSocket)
|
||||
{
|
||||
ERRLOG3(g_Log, "Connected socket creation error : %d, destination : %s:%d",
|
||||
WSAGetLastError(), lpConnectAddress, usPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
CSession* lpSession = m_lpSessionMgr->CreateSession(*lpSessionPolicy);
|
||||
|
||||
if(0 != lpSession)
|
||||
{
|
||||
if(m_lpSocketHandler->AttachToHander(
|
||||
reinterpret_cast<HANDLE>(hConnectedSocket),
|
||||
reinterpret_cast<ULONG_PTR>(lpSession)))
|
||||
{
|
||||
lpSession->Socket(hConnectedSocket);
|
||||
lpSession->SetAddress(INET_Addr(lpConnectAddress, usPort), INET_Addr());
|
||||
|
||||
DETLOG3(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ Connect Success.",
|
||||
lpSession, lpSession->GetDispatch(), lpConnectAddress);
|
||||
|
||||
lpSession->InternalRecv();
|
||||
|
||||
m_lpSessionMgr->Add(lpSession);
|
||||
|
||||
lpSessionPolicy->AddRef();
|
||||
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
++m_SessionPolicyMap[lpSessionPolicy];
|
||||
return true;
|
||||
}
|
||||
|
||||
m_lpSessionMgr->DeleteSession(lpSession);
|
||||
}
|
||||
|
||||
closesocket(hConnectedSocket);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Desc : Listener에 딸린 세션들과, ConnectedSession의 처리를 한다.
|
||||
void CIOCPNet::Process()
|
||||
{
|
||||
if(0 != m_lpSessionMgr)
|
||||
{
|
||||
m_lpSessionMgr->Process();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Desc : 모든 Listener와 세션을 종료한다.
|
||||
bool CIOCPNet::Destroy()
|
||||
{
|
||||
m_IOCPLock.Lock();
|
||||
|
||||
if(!(m_dwFlags & DESTROYED_IOCP))
|
||||
{
|
||||
CThreadMgr* lpThreadMgr = 0;
|
||||
CCompletionHandler* lpSocketHandler = 0;
|
||||
CSessionMgr* lpSessionMgr = 0;
|
||||
|
||||
SessionPolicyMap tempMap(m_SessionPolicyMap);
|
||||
m_SessionPolicyMap.clear();
|
||||
|
||||
std::swap(m_lpThreadMgr, lpThreadMgr);
|
||||
std::swap(m_lpSocketHandler, lpSocketHandler);
|
||||
std::swap(m_lpSessionMgr, lpSessionMgr);
|
||||
|
||||
m_dwFlags |= DESTROYED_IOCP;
|
||||
|
||||
m_IOCPLock.Unlock();
|
||||
|
||||
DestroyListener();
|
||||
|
||||
delete lpSessionMgr;
|
||||
delete lpThreadMgr;
|
||||
delete lpSocketHandler;
|
||||
|
||||
SessionPolicyMap::iterator pos = tempMap.begin();
|
||||
SessionPolicyMap::iterator end = tempMap.end();
|
||||
|
||||
for(; pos != end; ++pos)
|
||||
{
|
||||
for(unsigned int nReleaseCount = pos->second;
|
||||
0 != nReleaseCount; --nReleaseCount)
|
||||
{
|
||||
pos->first->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
m_IOCPLock.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CIOCPNet::DestroyListener()
|
||||
{
|
||||
ListenerList deleteList;
|
||||
|
||||
{
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
deleteList.splice(deleteList.end(), m_ListenerList);
|
||||
}
|
||||
|
||||
ListenerList::iterator pos = deleteList.begin();
|
||||
ListenerList::iterator end = deleteList.end();
|
||||
|
||||
for(; pos != end; ++pos)
|
||||
{
|
||||
delete (*pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Desc : 현재 Accept를 pending하고 있는 세션의 수를 리턴.
|
||||
unsigned long CIOCPNet::GetAcceptPendingNum()
|
||||
{
|
||||
unsigned long dwPendingNum = 0;
|
||||
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
|
||||
for(ListenerList::iterator itr = m_ListenerList.begin();
|
||||
itr != m_ListenerList.end(); ++itr)
|
||||
{
|
||||
dwPendingNum += (*itr)->GetPendingAcceptNum();
|
||||
}
|
||||
|
||||
return dwPendingNum;
|
||||
}
|
||||
|
||||
unsigned long CIOCPNet::GetSessionNum()
|
||||
{
|
||||
if(0 != m_lpSessionMgr)
|
||||
{
|
||||
return m_lpSessionMgr->GetSessionNum();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void CIOCPNet::LogListeners()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
|
||||
std::for_each(m_ListenerList.begin(), m_ListenerList.end(),
|
||||
std::mem_fun(CListener::LogListenerStatus));
|
||||
}
|
||||
|
||||
|
||||
void CIOCPNet::LogConnected()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
unsigned int nStateNum[CSession::MAX_SESSION_STATE];
|
||||
std::fill_n(nStateNum, unsigned int(CSession::MAX_SESSION_STATE), 0);
|
||||
|
||||
const char* szDelimiter = "// ------------------------------------------------------------------------------- ";
|
||||
|
||||
char szProgramName[MAX_PATH];
|
||||
char szFileName[MAX_PATH];
|
||||
char szTime[MAX_PATH];
|
||||
|
||||
SYSTEMTIME systemTime;
|
||||
GetLocalTime(&systemTime);
|
||||
|
||||
DbgUtils::SetProgramName(szProgramName, MAX_PATH);
|
||||
|
||||
_snprintf(szTime, MAX_PATH, "%04d%02d%02d-%02d%02d%02d",
|
||||
systemTime.wYear, systemTime.wMonth, systemTime.wDay,
|
||||
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
|
||||
|
||||
_snprintf(szFileName, MAX_PATH, "%s/ConnectedLog-%s.txt", szProgramName, szTime);
|
||||
|
||||
fstream logfile(szFileName, ios::out | ios::app);
|
||||
fstream::char_type endline = logfile.widen('\n');
|
||||
|
||||
logfile << szDelimiter << endline;
|
||||
|
||||
m_IOCPLock.Lock();
|
||||
|
||||
unsigned int nConnectedNum = 0;
|
||||
ConnectedArray::iterator first = m_ConnectedArray.begin();
|
||||
ConnectedArray::iterator last = m_ConnectedArray.end();
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
logfile << **first << endline;
|
||||
++nStateNum[(*first)->m_cCurrentStatus];
|
||||
++nConnectedNum;
|
||||
}
|
||||
|
||||
m_IOCPLock.Unlock();
|
||||
|
||||
logfile << endline << szDelimiter << endline
|
||||
<< "Time : " << szTime << endline << endline
|
||||
<< "nUNINITIALIZED : " << nStateNum[CSession::UNINITIALIZED] << endline
|
||||
<< "ACCEPT_PENDING : " << nStateNum[CSession::ACCEPT_PENDING] << endline
|
||||
<< "CONNECTED : " << nStateNum[CSession::CONNECTED] << endline
|
||||
<< "DISCONNECTED : " << nStateNum[CSession::DISCONNECTED] << endline
|
||||
<< "Total : " << nConnectedNum << endl;
|
||||
}
|
||||
|
||||
*/
|
||||
61
Server/RylServerProject/BaseLibrary/Network/Iocp/IOCPNet.h
Normal file
61
Server/RylServerProject/BaseLibrary/Network/Iocp/IOCPNet.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef _CIOCPMGR_H_
|
||||
#define _CIOCPMGR_H_
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "../../Thread/Lock.h"
|
||||
|
||||
// Àü¹æ ÂüÁ¶
|
||||
class CListener;
|
||||
class CSession;
|
||||
class CSessionPolicy;
|
||||
class CCompletionHandler;
|
||||
class CThreadMgr;
|
||||
class CSessionMgr;
|
||||
class CValidateConnection;
|
||||
|
||||
class CIOCPNet
|
||||
{
|
||||
public:
|
||||
|
||||
CIOCPNet();
|
||||
~CIOCPNet();
|
||||
|
||||
bool Initialize();
|
||||
bool Destroy();
|
||||
|
||||
bool AddListener(CSessionPolicy* lpSessionPolicy,
|
||||
const char* lpListenAddress, unsigned short usPort,
|
||||
unsigned long dwMaxListenPeding = 10,
|
||||
CValidateConnection* lpValidateConnection = 0);
|
||||
|
||||
bool Connect(CSessionPolicy* lpSessionPolicy,
|
||||
const char* lpConnectAddress, unsigned short usPort);
|
||||
|
||||
void Process();
|
||||
|
||||
unsigned long GetAcceptPendingNum();
|
||||
unsigned long GetSessionNum();
|
||||
|
||||
private:
|
||||
|
||||
void DestroyListener();
|
||||
|
||||
typedef std::list<CListener*> ListenerList;
|
||||
typedef std::map<CSessionPolicy*, unsigned int> SessionPolicyMap;
|
||||
|
||||
typedef CCSLock SessionLock;
|
||||
|
||||
SessionLock m_IOCPLock;
|
||||
CACHE_PAD(SessionLockPad, sizeof(SessionLock));
|
||||
|
||||
CCompletionHandler* m_lpSocketHandler;
|
||||
CThreadMgr* m_lpThreadMgr;
|
||||
CSessionMgr* m_lpSessionMgr;
|
||||
|
||||
ListenerList m_ListenerList;
|
||||
SessionPolicyMap m_SessionPolicyMap;
|
||||
unsigned long m_dwFlags;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "stdafx.h"
|
||||
#include "IOWorker.h"
|
||||
#include "Overlapped.h"
|
||||
|
||||
#include "../IOCP/CompletionHandler.h"
|
||||
#include "../Session/Session.h"
|
||||
#include "../Listener/Listener.h"
|
||||
|
||||
#include <Log/ServerLog.h>
|
||||
|
||||
CIOWorker::CIOWorker(CCompletionHandler& SocketHandler)
|
||||
: m_SocketHandler(SocketHandler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CIOWorker::~CIOWorker()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
unsigned int CIOWorker::Run()
|
||||
{
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
while(true)
|
||||
{
|
||||
unsigned long dwProcessedBytes = 0;
|
||||
ULONG_PTR lpSessionKey = 0;
|
||||
OVERLAPPED* lpOverlappedStruct = 0;
|
||||
|
||||
BOOL bResult = m_SocketHandler.GetHanderStatus(&dwProcessedBytes,
|
||||
&lpSessionKey, &lpOverlappedStruct);
|
||||
|
||||
if(0 == lpSessionKey)
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/lpOverlapped:0x%p/bResult:%s/Thread 0x%p Completed",
|
||||
lpSessionKey, lpOverlappedStruct, bResult ? "T" : "F", GetCurrentThreadId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!bResult && 0 == lpOverlappedStruct)
|
||||
{
|
||||
// 알 수 없는 에러, 혹은 타임아웃.
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/lpOverlapped:0x%p/bResult:%s/GetQueuedCompletionStatus error : %u",
|
||||
lpSessionKey, lpOverlappedStruct, bResult ? "T" : "F", WSAGetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Recv, Send, Accept를 함.
|
||||
lpOverlapped = static_cast<COverlapped*>(lpOverlappedStruct);
|
||||
lpOverlapped->Dispatch(bResult, lpSessionKey, dwProcessedBytes);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BOOL CIOWorker::End()
|
||||
{
|
||||
m_SocketHandler.PostToHandler(0, 0, 0);
|
||||
return true;
|
||||
}
|
||||
27
Server/RylServerProject/BaseLibrary/Network/Iocp/IOWorker.h
Normal file
27
Server/RylServerProject/BaseLibrary/Network/Iocp/IOWorker.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _IO_WORKER_H_
|
||||
#define _IO_WORKER_H_
|
||||
|
||||
#include "../../Thread/Thread.h"
|
||||
|
||||
// Àü¹æ ÂüÁ¶
|
||||
class CCompletionHandler;
|
||||
|
||||
class CIOWorker : public CThread
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
CIOWorker(CCompletionHandler& SocketHandler);
|
||||
virtual ~CIOWorker();
|
||||
|
||||
private:
|
||||
|
||||
virtual unsigned int Run();
|
||||
virtual BOOL End();
|
||||
|
||||
CCompletionHandler& m_SocketHandler;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
284
Server/RylServerProject/BaseLibrary/Network/Iocp/Overlapped.cpp
Normal file
284
Server/RylServerProject/BaseLibrary/Network/Iocp/Overlapped.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include "Overlapped.h"
|
||||
#include "../Session/Session.h"
|
||||
#include "../Listener/Listener.h"
|
||||
#include "../../Stream/Buffer/Buffer.h"
|
||||
#include "../../Stream/Buffer/BufferFactory.h"
|
||||
|
||||
#include <boost/pool/pool.hpp>
|
||||
|
||||
|
||||
COverlapped::COverlapped(COverlappedFactory& ovlFactory, CBuffer* lpBuffer)
|
||||
: m_lpBuffer(lpBuffer), m_ovlFactory(ovlFactory)
|
||||
{
|
||||
Internal = InternalHigh = Offset = OffsetHigh = 0;
|
||||
hEvent = 0;
|
||||
}
|
||||
|
||||
|
||||
COverlapped::~COverlapped()
|
||||
{
|
||||
SAFE_RELEASE_BUFFER(m_lpBuffer);
|
||||
}
|
||||
|
||||
void COverlapped::Release()
|
||||
{
|
||||
m_ovlFactory.DeleteOverlapped(this);
|
||||
}
|
||||
|
||||
class CSendOverlapped : public COverlapped
|
||||
{
|
||||
public:
|
||||
|
||||
CSendOverlapped(COverlappedFactory& ovlFactory, CBuffer* lpSendBuffer)
|
||||
: COverlapped(ovlFactory, lpSendBuffer) { }
|
||||
virtual ~CSendOverlapped() { }
|
||||
|
||||
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
|
||||
{
|
||||
CSession& Session = *reinterpret_cast<CSession*>(lpSessionKey);
|
||||
|
||||
Session.SendCompleted(bResult, dwProcessedBytes);
|
||||
m_ovlFactory.DeleteOverlapped(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CStreamRecvOverlapped : public COverlapped
|
||||
{
|
||||
public:
|
||||
|
||||
CStreamRecvOverlapped(COverlappedFactory& ovlFactory) : COverlapped(ovlFactory, 0) { }
|
||||
virtual ~CStreamRecvOverlapped() { }
|
||||
|
||||
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
|
||||
{
|
||||
CSession& Session = *reinterpret_cast<CSession*>(lpSessionKey);
|
||||
|
||||
if(Session.Dispatch(dwProcessedBytes))
|
||||
{
|
||||
Session.Recv();
|
||||
}
|
||||
|
||||
m_ovlFactory.DeleteOverlapped(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CDatagramRecvOverlapped : public COverlapped
|
||||
{
|
||||
public:
|
||||
|
||||
CDatagramRecvOverlapped(COverlappedFactory& ovlFactory) : COverlapped(ovlFactory, 0) { }
|
||||
virtual ~CDatagramRecvOverlapped() { }
|
||||
|
||||
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
|
||||
{
|
||||
CSession& Session = *reinterpret_cast<CSession*>(lpSessionKey);
|
||||
|
||||
if(Session.Dispatch(dwProcessedBytes))
|
||||
{
|
||||
Session.RecvFrom();
|
||||
}
|
||||
|
||||
m_ovlFactory.DeleteOverlapped(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CAcceptOverlapped : public COverlapped
|
||||
{
|
||||
public:
|
||||
|
||||
CAcceptOverlapped(COverlappedFactory& ovlFactory, CListener& Listener, SOCKET hSocket, CBuffer* lpAddrBuffer)
|
||||
: COverlapped(ovlFactory, lpAddrBuffer), m_Listener(Listener), m_hSocket(hSocket)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual ~CAcceptOverlapped() { }
|
||||
|
||||
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
|
||||
{
|
||||
CListener& Listener = *reinterpret_cast<CListener*>(lpSessionKey);
|
||||
|
||||
Listener.ProcessAccept(bResult, m_hSocket, m_lpBuffer, dwProcessedBytes);
|
||||
m_ovlFactory.DeleteOverlapped(this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CListener& m_Listener;
|
||||
SOCKET m_hSocket;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StreamOverlapped
|
||||
|
||||
CStreamOverlappedFactory::CStreamOverlappedFactory()
|
||||
{
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
size_t nMaxPoolSize = std::max(sizeof(CAcceptOverlapped),
|
||||
std::max(sizeof(CSendOverlapped), sizeof(CStreamRecvOverlapped)));
|
||||
|
||||
m_lpOverlappedPool = new (std::nothrow) boost::pool<>(nMaxPoolSize);
|
||||
}
|
||||
|
||||
|
||||
CStreamOverlappedFactory::~CStreamOverlappedFactory()
|
||||
{
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
delete m_lpOverlappedPool;
|
||||
m_lpOverlappedPool = 0;
|
||||
}
|
||||
|
||||
|
||||
COverlapped* CStreamOverlappedFactory::CreateSend(CSession* lpSession, CBuffer* lpMsgBlock)
|
||||
{
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
void* lpBuffer = m_lpOverlappedPool->malloc();
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = new (lpBuffer) CSendOverlapped(*this, lpMsgBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return lpOverlapped;
|
||||
}
|
||||
|
||||
COverlapped* CStreamOverlappedFactory::CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock)
|
||||
{
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
void* lpBuffer = m_lpOverlappedPool->malloc();
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = new (lpBuffer) CStreamRecvOverlapped(*this);
|
||||
}
|
||||
}
|
||||
|
||||
return lpOverlapped;
|
||||
}
|
||||
|
||||
COverlapped* CStreamOverlappedFactory::CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock)
|
||||
{
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpListener && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
void* lpBuffer = m_lpOverlappedPool->malloc();
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = new (lpBuffer) CAcceptOverlapped(*this, *lpListener, hSocket, lpMsgBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return lpOverlapped;
|
||||
}
|
||||
|
||||
void CStreamOverlappedFactory::DeleteOverlapped(COverlapped* lpOverlapped)
|
||||
{
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpOverlapped && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
lpOverlapped->~COverlapped();
|
||||
m_lpOverlappedPool->free(lpOverlapped);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// DatagramOverlapped
|
||||
|
||||
|
||||
CDatagramOverlappedFactory::CDatagramOverlappedFactory()
|
||||
{
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
size_t nMaxPoolSize = std::max(sizeof(CAcceptOverlapped),
|
||||
std::max(sizeof(CSendOverlapped), sizeof(CDatagramRecvOverlapped)));
|
||||
|
||||
m_lpOverlappedPool = new (std::nothrow) boost::pool<>(nMaxPoolSize);
|
||||
}
|
||||
|
||||
|
||||
CDatagramOverlappedFactory::~CDatagramOverlappedFactory()
|
||||
{
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
delete m_lpOverlappedPool;
|
||||
m_lpOverlappedPool = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
COverlapped* CDatagramOverlappedFactory::CreateSend(CSession* lpSession, CBuffer* lpMsgBlock)
|
||||
{
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
void* lpBuffer = m_lpOverlappedPool->malloc();
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = new (lpBuffer) CSendOverlapped(*this, lpMsgBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return lpOverlapped;
|
||||
}
|
||||
|
||||
COverlapped* CDatagramOverlappedFactory::CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock)
|
||||
{
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
void* lpBuffer = m_lpOverlappedPool->malloc();
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = new (lpBuffer) CDatagramRecvOverlapped(*this);
|
||||
}
|
||||
}
|
||||
|
||||
return lpOverlapped;
|
||||
}
|
||||
|
||||
void CDatagramOverlappedFactory::DeleteOverlapped(COverlapped* lpOverlapped)
|
||||
{
|
||||
FactoryLock::Syncronize sync(m_Lock);
|
||||
|
||||
if(0 != lpOverlapped && 0 != m_lpOverlappedPool)
|
||||
{
|
||||
lpOverlapped->~COverlapped();
|
||||
m_lpOverlappedPool->free(lpOverlapped);
|
||||
}
|
||||
}
|
||||
112
Server/RylServerProject/BaseLibrary/Network/Iocp/Overlapped.h
Normal file
112
Server/RylServerProject/BaseLibrary/Network/Iocp/Overlapped.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef _COVERLAPPED_H_
|
||||
#define _COVERLAPPED_H_
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include "../../Thread/Lock.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <boost/pool/poolfwd.hpp>
|
||||
|
||||
// 전방 참조
|
||||
class CBuffer;
|
||||
class CBufferFactory;
|
||||
class CSession;
|
||||
class CListener;
|
||||
class COverlappedFactory;
|
||||
|
||||
class COverlapped : public OVERLAPPED
|
||||
{
|
||||
public:
|
||||
|
||||
COverlapped(COverlappedFactory& ovlFactory, CBuffer* lpBuffer);
|
||||
virtual ~COverlapped();
|
||||
|
||||
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey,
|
||||
unsigned long dwProcessedBytes) = 0;
|
||||
|
||||
void SetBuffer(CBuffer* lpBuffer) { m_lpBuffer = lpBuffer; }
|
||||
void Release();
|
||||
|
||||
protected:
|
||||
|
||||
COverlappedFactory& m_ovlFactory;
|
||||
CBuffer* m_lpBuffer;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// COverlappedFactory : 인터페이스 팩토리
|
||||
|
||||
class COverlappedFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~COverlappedFactory() { }
|
||||
|
||||
virtual COverlapped* CreateSend(CSession* lpSession, CBuffer* lpMsgBlock) = 0;
|
||||
virtual COverlapped* CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock) = 0;
|
||||
virtual COverlapped* CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock) = 0;
|
||||
|
||||
virtual void DeleteOverlapped(COverlapped* lpOverlapped) = 0;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CStreamOverlappedFactory : TCP, SPX통신에 사용한다.
|
||||
|
||||
class CStreamOverlappedFactory : public COverlappedFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CStreamOverlappedFactory();
|
||||
virtual ~CStreamOverlappedFactory();
|
||||
|
||||
virtual COverlapped* CreateSend(CSession* lpSession, CBuffer* lpMsgBlock);
|
||||
virtual COverlapped* CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock);
|
||||
virtual COverlapped* CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock);
|
||||
|
||||
virtual void DeleteOverlapped(COverlapped* lpOverlapped);
|
||||
|
||||
private:
|
||||
|
||||
typedef CCSLock FactoryLock;
|
||||
|
||||
FactoryLock m_Lock;
|
||||
CACHE_PAD(FactoryLockPad, sizeof(FactoryLock));
|
||||
|
||||
boost::pool<>* m_lpOverlappedPool;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CDatagramOverlappedFactory : UDP, IPX통신에 사용한다.
|
||||
|
||||
class CDatagramOverlappedFactory : public COverlappedFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDatagramOverlappedFactory();
|
||||
virtual ~CDatagramOverlappedFactory();
|
||||
|
||||
virtual COverlapped* CreateSend(CSession* lpSession, CBuffer* lpMsgBlock);
|
||||
virtual COverlapped* CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock);
|
||||
virtual COverlapped* CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock) { return 0; }
|
||||
|
||||
virtual void DeleteOverlapped(COverlapped* lpOverlapped);
|
||||
|
||||
private:
|
||||
|
||||
typedef CCSLock FactoryLock;
|
||||
|
||||
FactoryLock m_Lock;
|
||||
CACHE_PAD(FactoryLockPad, sizeof(FactoryLock));
|
||||
|
||||
boost::pool<>* m_lpOverlappedPool;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user