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,36 @@
|
||||
#include "stdafx.h"
|
||||
#include "INET_Addr.h"
|
||||
#include "GMMemory.h"
|
||||
|
||||
void INET_Addr::set_addr(const char* addr, const unsigned short port)
|
||||
{
|
||||
memset(&m_SockAddr, 0, sizeof(sockaddr));
|
||||
sockaddr_in& addr_in = *reinterpret_cast<sockaddr_in*>(&m_SockAddr);
|
||||
|
||||
addr_in.sin_family = AF_INET;
|
||||
addr_in.sin_addr.s_addr = (NULL == addr) ? htonl(INADDR_ANY) : inet_addr(addr);
|
||||
addr_in.sin_port = (0 == port) ? 0 : htons(port);
|
||||
|
||||
m_iAddrLen = sizeof(sockaddr_in);
|
||||
}
|
||||
|
||||
|
||||
void INET_Addr::set_addr(const sockaddr& addr, const int size)
|
||||
{
|
||||
m_SockAddr = addr;
|
||||
m_iAddrLen = size;
|
||||
}
|
||||
|
||||
|
||||
void INET_Addr::set_addr(const IN_ADDR addr, const unsigned short port)
|
||||
{
|
||||
memset(&m_SockAddr, 0, sizeof(sockaddr));
|
||||
sockaddr_in& addr_in = *reinterpret_cast<sockaddr_in*>(&m_SockAddr);
|
||||
|
||||
addr_in.sin_family = AF_INET;
|
||||
addr_in.sin_addr = addr;
|
||||
addr_in.sin_port = (0 == port) ? 0 : htons(port);
|
||||
|
||||
m_iAddrLen = sizeof(sockaddr_in);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef _GAMA_INET_ADDR_
|
||||
#define _GAMA_INET_ADDR_
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
|
||||
class INET_Addr
|
||||
{
|
||||
public:
|
||||
|
||||
INET_Addr() : m_iAddrLen(0) { memset(&m_SockAddr, 0, sizeof(SOCKADDR)); }
|
||||
INET_Addr(const char* addr, unsigned short port) { set_addr(addr, port); }
|
||||
INET_Addr(IN_ADDR addr, unsigned short port) { set_addr(addr, port); }
|
||||
INET_Addr(sockaddr& addr, int size) { set_addr(addr, size); }
|
||||
~INET_Addr() { }
|
||||
|
||||
void clear() { m_iAddrLen = 0; memset(&m_SockAddr, 0, sizeof(SOCKADDR)); }
|
||||
|
||||
void set_addr(const char* addr, const unsigned short port);
|
||||
void set_addr(const IN_ADDR addr, const unsigned short port);
|
||||
void set_addr(const sockaddr& addr, const int size);
|
||||
|
||||
// Winsock<63>Լ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> const<73><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʾ<EFBFBD><CABE><EFBFBD>.
|
||||
sockaddr& get_addr() { return m_SockAddr; }
|
||||
|
||||
const sockaddr_in& get_addr_in() const { return reinterpret_cast<const sockaddr_in&>(m_SockAddr); }
|
||||
unsigned short get_port_in() const { return ntohs(reinterpret_cast<const sockaddr_in&>(m_SockAddr).sin_port); }
|
||||
const char* get_addr_string() const { return inet_ntoa(reinterpret_cast<const sockaddr_in&>(m_SockAddr).sin_addr); }
|
||||
|
||||
int get_size() const { return m_iAddrLen; }
|
||||
|
||||
int* get_size_ptr() { return &m_iAddrLen; }
|
||||
void set_size(int n) { m_iAddrLen = n; }
|
||||
|
||||
static int get_addr_buffer_size() { return sizeof(sockaddr); }
|
||||
|
||||
private:
|
||||
|
||||
sockaddr m_SockAddr;
|
||||
int m_iAddrLen;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "stdafx.h"
|
||||
#include "Dispatch.h"
|
||||
|
||||
#include "../Session/Session.h"
|
||||
#include "../../Stream/Buffer/Buffer.h"
|
||||
#include "../../Stream/Buffer/BufferFactory.h"
|
||||
|
||||
#include "PoolDispatchFactory.h"
|
||||
|
||||
#include "../../Log/ServerLog.h"
|
||||
|
||||
void CEchoDispatch::Connected()
|
||||
{
|
||||
DETLOG1(g_Log, "this:0x%p Connected", this);
|
||||
}
|
||||
|
||||
void CEchoDispatch::Disconnected()
|
||||
{
|
||||
DETLOG1(g_Log, "this:0x%p Disconnected", this);
|
||||
}
|
||||
|
||||
bool CEchoDispatch::ParsePacket (char* const lpStream_In, unsigned long* dwStreamSIze_InOut)
|
||||
{
|
||||
unsigned long dwReceived = *dwStreamSIze_InOut;
|
||||
|
||||
CBuffer* lpEchoBuffer = CREATE_BUFFER(m_Session.GetPolicy().GetBufferFactory(), dwReceived);
|
||||
memcpy(lpEchoBuffer->wr_ptr(), lpStream_In, dwReceived);
|
||||
lpEchoBuffer->wr_ptr(dwReceived);
|
||||
|
||||
return m_Session.SendPending(lpEchoBuffer);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef _GAMA_SERVER_NETWORK_DISPATCH_H_
|
||||
#define _GAMA_SERVER_NETWORK_DISPATCH_H_
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
class CSession;
|
||||
|
||||
// Session<6F><6E><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> DispatchŬ<68><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD>.
|
||||
class CPacketDispatch
|
||||
{
|
||||
public:
|
||||
|
||||
CPacketDispatch(CSession& Session) : m_Session(Session) { }
|
||||
virtual ~CPacketDispatch() { }
|
||||
|
||||
// In : char* const lpStream_In <20><><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE>
|
||||
// unsigned long* dwStreamSize_InOut <20><><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
// out : Return <20><>Ŷ <20>Ľ<EFBFBD> <20><><EFBFBD><EFBFBD> / <20><><EFBFBD><EFBFBD>(<28><><EFBFBD>н<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
|
||||
// unsigned long* dwStreamSize_InOut <20>Ľ<EFBFBD><C4BD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
virtual bool ParsePacket(char* const lpStream_In, unsigned long* dwStreamSize_InOut) = 0;
|
||||
virtual bool Dispatch() = 0;
|
||||
|
||||
virtual void Connected() { }
|
||||
virtual void Disconnected() { }
|
||||
|
||||
CSession& GetSession() { return m_Session; }
|
||||
|
||||
protected:
|
||||
|
||||
CSession& m_Session;
|
||||
};
|
||||
|
||||
|
||||
class CDispatchFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CDispatchFactory() = 0;
|
||||
|
||||
virtual CPacketDispatch* CreateDispatch(CSession& Session) = 0;
|
||||
virtual void DeleteDispatch(CPacketDispatch* lpDispatch) = 0;
|
||||
};
|
||||
|
||||
inline CDispatchFactory::~CDispatchFactory() { }
|
||||
|
||||
|
||||
template<typename DispatchType>
|
||||
class CDefaultDispatchFactory : public CDispatchFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CDefaultDispatchFactory() { }
|
||||
|
||||
virtual CPacketDispatch* CreateDispatch(CSession& Session) { return new DispatchType(Session); }
|
||||
virtual void DeleteDispatch(CPacketDispatch* lpDispatch) { delete lpDispatch; }
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// <20><EFBFBD>Ʈ<EFBFBD><C6AE> Sample Dispatchers....
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
|
||||
class CNullDispatch : public CPacketDispatch
|
||||
{
|
||||
public:
|
||||
|
||||
CNullDispatch(CSession& Session) : CPacketDispatch(Session) { }
|
||||
virtual ~CNullDispatch() { }
|
||||
|
||||
virtual bool ParsePacket (char* const lpStream_In, unsigned long* dwStreamSIze_InOut) { return true; }
|
||||
virtual bool Dispatch() { return true; }
|
||||
};
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20>״<EFBFBD><D7B4><EFBFBD> <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ش<EFBFBD>.
|
||||
class CEchoDispatch : public CPacketDispatch
|
||||
{
|
||||
public:
|
||||
|
||||
CEchoDispatch(CSession& Session) : CPacketDispatch(Session) { }
|
||||
virtual ~CEchoDispatch() { }
|
||||
|
||||
virtual void Connected();
|
||||
virtual void Disconnected();
|
||||
|
||||
virtual bool ParsePacket (char* const lpStream_In, unsigned long* dwStreamSIze_InOut);
|
||||
virtual bool Dispatch() { return true; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef _GAMA_SERVER_NETWORK_POOL_DISPATCH_FACTORY_H_
|
||||
#define _GAMA_SERVER_NETWORK_POOL_DISPATCH_FACTORY_H_
|
||||
|
||||
#include "Dispatch.h"
|
||||
#include <boost/pool/pool.hpp>
|
||||
|
||||
template<typename DispatchType>
|
||||
class CPoolDispatchFactory : public CDispatchFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CPoolDispatchFactory() : m_DispatchPool(sizeof(DispatchType)) { }
|
||||
virtual ~CPoolDispatchFactory() { }
|
||||
|
||||
virtual CPacketDispatch* CreateDispatch(CSession& Session)
|
||||
{
|
||||
void* ptr = m_DispatchPool.malloc();
|
||||
return new (ptr) DispatchType(Session);
|
||||
}
|
||||
|
||||
virtual void DeleteDispatch(CPacketDispatch* lpDispatch)
|
||||
{
|
||||
lpDispatch->~CPacketDispatch();
|
||||
m_DispatchPool.free(lpDispatch);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef boost::pool<> DispatchPool;
|
||||
|
||||
DispatchPool m_DispatchPool;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,272 @@
|
||||
#include "stdafx.h"
|
||||
#include "ServerRequest.h"
|
||||
|
||||
#include <Network/Session/Session.h>
|
||||
#include <Network/Dispatch/Dispatch.h>
|
||||
|
||||
#include <Log/ServerLog.h>
|
||||
|
||||
|
||||
#define REQUEST_LOG(x) x
|
||||
|
||||
|
||||
enum RequestConst
|
||||
{
|
||||
CANNOT_ADD_REQUEST = (1 << 0)
|
||||
};
|
||||
|
||||
|
||||
CServerRequest& CServerRequest::GetInstance()
|
||||
{
|
||||
static CServerRequest serverRequest;
|
||||
return serverRequest;
|
||||
}
|
||||
|
||||
|
||||
CServerRequest::Result::Result(unsigned long dwRequestKey, bool bRemove)
|
||||
: m_bRemove(bRemove)
|
||||
{
|
||||
m_lpSrcDispatch = bRemove
|
||||
// Request<73><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
? CServerRequest::GetInstance().PopRequest(dwRequestKey)
|
||||
|
||||
// Request<73><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
|
||||
: CServerRequest::GetInstance().GetRequest(dwRequestKey);
|
||||
}
|
||||
|
||||
|
||||
CServerRequest::Result::~Result()
|
||||
{
|
||||
if(0 != m_lpSrcDispatch && m_bRemove)
|
||||
{
|
||||
m_lpSrcDispatch->GetSession().Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSession* CServerRequest::Result::GetSession()
|
||||
{
|
||||
return (0 != m_lpSrcDispatch) ? &m_lpSrcDispatch->GetSession() : 0;
|
||||
}
|
||||
|
||||
|
||||
void CServerRequest::RequestInfo::ProcessRemove()
|
||||
{
|
||||
if(m_lpSrcDispatch)
|
||||
{
|
||||
if(m_lpTimeoutRequest)
|
||||
{
|
||||
m_lpTimeoutRequest(m_lpSrcDispatch);
|
||||
}
|
||||
|
||||
m_lpSrcDispatch->GetSession().Release();
|
||||
}
|
||||
|
||||
if(m_lpDstDispatch)
|
||||
{
|
||||
m_lpDstDispatch->GetSession().Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// return value : RequestKey
|
||||
unsigned long CServerRequest::AddRequest(CPacketDispatch* lpSrcDispatch,
|
||||
CPacketDispatch* lpDstDispatch,
|
||||
unsigned long dwDurationSec,
|
||||
TimeoutRequest lpTimeoutRequest)
|
||||
{
|
||||
if( 0 != lpSrcDispatch &&
|
||||
0 != lpDstDispatch &&
|
||||
0 != dwDurationSec)
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
|
||||
if(!(m_dwRequestFlags & CANNOT_ADD_REQUEST))
|
||||
{
|
||||
CSession& SrcSession = lpSrcDispatch->GetSession();
|
||||
CSession& DstSession = lpDstDispatch->GetSession();
|
||||
|
||||
if(0 == m_dwRequestCounter)
|
||||
{
|
||||
++m_dwRequestCounter;
|
||||
}
|
||||
|
||||
unsigned long dwRequestCounter = m_dwRequestCounter++;
|
||||
|
||||
if(m_RequestMap.insert(std::make_pair(dwRequestCounter,
|
||||
RequestInfo(lpSrcDispatch, lpDstDispatch, dwDurationSec, lpTimeoutRequest))).second)
|
||||
{
|
||||
SrcSession.AddRef();
|
||||
DstSession.AddRef();
|
||||
|
||||
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Added",
|
||||
&lpSrcDispatch->GetSession(), lpSrcDispatch,
|
||||
lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
|
||||
dwRequestCounter, lpDstDispatch));
|
||||
|
||||
return dwRequestCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CServerRequest::RemoveRequest(unsigned long dwRequestKey)
|
||||
{
|
||||
m_RequestLock.Lock();
|
||||
|
||||
RequestMap::iterator pos = m_RequestMap.find(dwRequestKey);
|
||||
RequestMap::iterator end = m_RequestMap.end();
|
||||
|
||||
RequestInfo info;
|
||||
|
||||
if(pos != end)
|
||||
{
|
||||
info = pos->second;
|
||||
|
||||
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By RequestKey)",
|
||||
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
|
||||
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
|
||||
pos->first, info.m_lpDstDispatch));
|
||||
|
||||
pos = m_RequestMap.erase(pos);
|
||||
}
|
||||
|
||||
m_RequestLock.Unlock();
|
||||
|
||||
info.ProcessRemove();
|
||||
}
|
||||
|
||||
void CServerRequest::RemoveRequest(CPacketDispatch* lpDispatch)
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
|
||||
RequestMap::iterator pos = m_RequestMap.begin();
|
||||
RequestMap::iterator end = m_RequestMap.end();
|
||||
|
||||
for(; pos != end;)
|
||||
{
|
||||
RequestInfo& info = pos->second;
|
||||
|
||||
if(lpDispatch == info.m_lpSrcDispatch ||
|
||||
lpDispatch == info.m_lpDstDispatch)
|
||||
{
|
||||
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By TargetPtr)",
|
||||
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
|
||||
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
|
||||
pos->first, info.m_lpDstDispatch));
|
||||
|
||||
info.ProcessRemove();
|
||||
pos = m_RequestMap.erase(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CServerRequest::RemoveTimeoutRequest()
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
|
||||
RequestMap::iterator pos = m_RequestMap.begin();
|
||||
RequestMap::iterator end = m_RequestMap.end();
|
||||
|
||||
for(; pos != end;)
|
||||
{
|
||||
RequestInfo& info = pos->second;
|
||||
|
||||
if(0 == --(info.m_dwDurationSec))
|
||||
{
|
||||
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By Timeout)",
|
||||
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
|
||||
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
|
||||
pos->first, info.m_lpDstDispatch));
|
||||
|
||||
info.ProcessRemove();
|
||||
pos = m_RequestMap.erase(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CServerRequest::RemoveAllRequest()
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
|
||||
RequestMap::iterator pos = m_RequestMap.begin();
|
||||
RequestMap::iterator end = m_RequestMap.end();
|
||||
|
||||
for(; pos != end; ++pos)
|
||||
{
|
||||
pos->second.ProcessRemove();
|
||||
}
|
||||
|
||||
m_RequestMap.clear();
|
||||
}
|
||||
|
||||
|
||||
void CServerRequest::RequestOn()
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
m_dwRequestFlags &= ~CANNOT_ADD_REQUEST;
|
||||
}
|
||||
|
||||
void CServerRequest::RequestOff()
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
m_dwRequestFlags |= CANNOT_ADD_REQUEST;
|
||||
}
|
||||
|
||||
|
||||
CServerRequest::CServerRequest()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
CServerRequest::~CServerRequest()
|
||||
{
|
||||
RequestOff();
|
||||
RemoveAllRequest();
|
||||
}
|
||||
|
||||
|
||||
CPacketDispatch* CServerRequest::GetRequest(unsigned long dwRequestKey)
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
|
||||
RequestMap::iterator pos = m_RequestMap.find(dwRequestKey);
|
||||
return (pos != m_RequestMap.end()) ? pos->second.m_lpSrcDispatch : 0;
|
||||
}
|
||||
|
||||
|
||||
CPacketDispatch* CServerRequest::PopRequest(unsigned long dwRequestKey)
|
||||
{
|
||||
LockType::Syncronize sync(m_RequestLock);
|
||||
|
||||
RequestMap::iterator pos = m_RequestMap.find(dwRequestKey);
|
||||
|
||||
if(pos != m_RequestMap.end())
|
||||
{
|
||||
RequestInfo info = pos->second;
|
||||
|
||||
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By Pop Request)",
|
||||
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
|
||||
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
|
||||
pos->first, info.m_lpDstDispatch));
|
||||
|
||||
m_RequestMap.erase(pos);
|
||||
return info.m_lpSrcDispatch;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef _SERVER_REQUEST_H_
|
||||
#define _SERVER_REQUEST_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <Thread/Lock.h>
|
||||
|
||||
class CSession;
|
||||
class CPacketDispatch;
|
||||
|
||||
class CServerRequest
|
||||
{
|
||||
public:
|
||||
|
||||
typedef void (*TimeoutRequest)(CPacketDispatch* lpSrcDispatch);
|
||||
|
||||
static CServerRequest& GetInstance();
|
||||
|
||||
// return value : RequestKey
|
||||
unsigned long AddRequest(CPacketDispatch* lpSrcDispatch, CPacketDispatch* lpDstDispatch,
|
||||
unsigned long dwDurationSec, TimeoutRequest lpTimeoutRequest = 0);
|
||||
|
||||
void RemoveRequest(unsigned long dwRequestKey);
|
||||
void RemoveRequest(CPacketDispatch* lpDispatch);
|
||||
|
||||
void RemoveTimeoutRequest();
|
||||
void RemoveAllRequest();
|
||||
|
||||
void RequestOn();
|
||||
void RequestOff();
|
||||
|
||||
class Result
|
||||
{
|
||||
public:
|
||||
|
||||
explicit Result(unsigned long dwRequestKey, bool bRemove = true);
|
||||
~Result();
|
||||
|
||||
CPacketDispatch* GetDispatch() { return m_lpSrcDispatch; }
|
||||
CSession* GetSession();
|
||||
|
||||
private:
|
||||
|
||||
// new <20><> delete<74><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><>.
|
||||
void* operator new (size_t size);
|
||||
void operator delete (void* ptr);
|
||||
|
||||
CPacketDispatch* m_lpSrcDispatch;
|
||||
bool m_bRemove;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
CServerRequest();
|
||||
~CServerRequest();
|
||||
|
||||
// return value : SrcRequest
|
||||
CPacketDispatch* GetRequest(unsigned long dwRequestKey);
|
||||
CPacketDispatch* PopRequest(unsigned long dwRequestKey);
|
||||
|
||||
struct RequestInfo
|
||||
{
|
||||
CPacketDispatch* m_lpSrcDispatch;
|
||||
CPacketDispatch* m_lpDstDispatch;
|
||||
unsigned long m_dwDurationSec;
|
||||
TimeoutRequest m_lpTimeoutRequest;
|
||||
|
||||
RequestInfo()
|
||||
: m_lpSrcDispatch(0),
|
||||
m_lpDstDispatch(0),
|
||||
m_dwDurationSec(0),
|
||||
m_lpTimeoutRequest(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RequestInfo(CPacketDispatch* lpSrcDispatch, CPacketDispatch* lpDstDispatch,
|
||||
unsigned long dwDurationSec, TimeoutRequest lpTimeoutRequest)
|
||||
: m_lpSrcDispatch(lpSrcDispatch),
|
||||
m_lpDstDispatch(lpDstDispatch),
|
||||
m_dwDurationSec(dwDurationSec),
|
||||
m_lpTimeoutRequest(lpTimeoutRequest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ProcessRemove();
|
||||
};
|
||||
|
||||
typedef CCSLock LockType;
|
||||
typedef std::map<unsigned long, RequestInfo> RequestMap;
|
||||
|
||||
LockType m_RequestLock;
|
||||
CACHE_PAD(RequestLock, sizeof(LockType));
|
||||
|
||||
RequestMap m_RequestMap;
|
||||
unsigned long m_dwRequestCounter;
|
||||
unsigned long m_dwRequestFlags;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -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<65><72> <20>ʱ<EFBFBD>ȭ<EFBFBD>Ѵ<EFBFBD>.
|
||||
bool Destroy(); // Completion Hander<65><72> <20>Ҹ<EFBFBD><D2B8><EFBFBD>Ų<EFBFBD><C5B2>.
|
||||
|
||||
bool AttachToHander(HANDLE hAttach, ULONG_PTR pCompletionKey); // Completion Handler<65><72> <20><> <20>ڵ<EFBFBD><DAB5><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.
|
||||
|
||||
BOOL GetHanderStatus(LPDWORD lpNumOfBytes,
|
||||
PULONG_PTR lpCompletionKey, LPOVERLAPPED *lpOverlapped); // <20>۾<EFBFBD><DBBE><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>´<EFBFBD>. <20><EFBFBD><D7B5><EFBFBD><EFBFBD><EFBFBD> block<63>ȴ<EFBFBD>.
|
||||
|
||||
BOOL PostToHandler(unsigned long dwNumOfBytesTransfered,
|
||||
ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped); // Handler<65><72> <20>۾<EFBFBD><DBBE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 : <20>ʱ<EFBFBD>ȭ <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
bool CIOCPNet::Initialize()
|
||||
{
|
||||
{
|
||||
SessionLock::Syncronize sync(m_IOCPLock);
|
||||
|
||||
// <20>ʱ<EFBFBD>ȭ<EFBFBD><C8AD> <20>ѹ<EFBFBD><D1B9><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD>.
|
||||
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 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
unsigned long dwThreadNum = GetOptimalThreadNum();
|
||||
while(0 != dwThreadNum--)
|
||||
{
|
||||
if(!m_lpThreadMgr->RegisterAndRun(
|
||||
new (std::nothrow) CIOWorker(*m_lpSocketHandler)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Desc : Listener<65><72> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
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 : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
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<65><72> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>, ConnectedSession<6F><6E> ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
|
||||
void CIOCPNet::Process()
|
||||
{
|
||||
if(0 != m_lpSessionMgr)
|
||||
{
|
||||
m_lpSessionMgr->Process();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Desc : <20><><EFBFBD><EFBFBD> Listener<65><72> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
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 : <20><><EFBFBD><EFBFBD> Accept<70><74> pending<6E>ϰ<EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
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"
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
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)
|
||||
{
|
||||
// <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, Ȥ<><C8A4> Ÿ<>Ӿƿ<D3BE>.
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/lpOverlapped:0x%p/bResult:%s/GetQueuedCompletionStatus error : %u",
|
||||
lpSessionKey, lpOverlappedStruct, bResult ? "T" : "F", WSAGetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Recv, Send, Accept<70><74> <20><>.
|
||||
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"
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
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>
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
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 : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD> <20><><EFBFBD>丮
|
||||
|
||||
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<50><58><EFBFBD>ſ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
|
||||
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<50><58><EFBFBD>ſ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
|
||||
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
|
||||
@@ -0,0 +1,395 @@
|
||||
#include "stdafx.h"
|
||||
#include "Listener.h"
|
||||
|
||||
#include "../Session/Session.h"
|
||||
#include "../Session/SessionMgr.h"
|
||||
#include "../Dispatch/Dispatch.h"
|
||||
#include "../Winsock/SocketFactory.h"
|
||||
|
||||
#include "../IOCP/CompletionHandler.h"
|
||||
#include "../IOCP/Overlapped.h"
|
||||
|
||||
#include "../../Stream/Buffer/Buffer.h"
|
||||
#include "../../Stream/Buffer/BufferFactory.h"
|
||||
|
||||
#include "../../Utility/Debug/DebugUtils.h"
|
||||
#include "../../Utility/Resource/EnsureCleanup.h"
|
||||
|
||||
#include "../../Log/ServerLog.h"
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
enum LISTENER_CONSTANT
|
||||
{
|
||||
DEFAULT_PENDING_NUM = 10
|
||||
};
|
||||
|
||||
|
||||
|
||||
CListener::CListener(CCompletionHandler& SocketHandler,
|
||||
CSessionPolicy& SessionPolicy,
|
||||
CSessionMgr& SessionMgr,
|
||||
CValidateConnection* lpValidateConnection)
|
||||
: m_hListen(INVALID_SOCKET),
|
||||
m_dwMaxPending(DEFAULT_PENDING_NUM),
|
||||
m_dwCurrentPending(0),
|
||||
m_dwTotalPendingCount(0),
|
||||
m_dwTotalAcceptCompleteCount(0),
|
||||
m_SocketHandler(SocketHandler),
|
||||
m_SessionPolicy(SessionPolicy),
|
||||
m_SessionMgr(SessionMgr),
|
||||
m_lpValidateConnection(lpValidateConnection)
|
||||
{
|
||||
m_SessionPolicy.AddRef();
|
||||
|
||||
if(0 != m_lpValidateConnection)
|
||||
{
|
||||
m_lpValidateConnection->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CListener::~CListener()
|
||||
{
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
InternalCloseListen();
|
||||
}
|
||||
|
||||
WaitForPendingComplete(5000);
|
||||
|
||||
m_SessionPolicy.Release();
|
||||
|
||||
if(0 != m_lpValidateConnection)
|
||||
{
|
||||
m_lpValidateConnection->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CListener::Initialize(INET_Addr& addrListen, unsigned long dwMaxPending)
|
||||
{
|
||||
if(!m_SessionPolicy.IsValid())
|
||||
{
|
||||
ERRLOG0(g_SessionLog, "CListener initialized failed : Invalid SessionPolicy");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
|
||||
InternalCloseListen();
|
||||
|
||||
const sockaddr_in& addr_in = addrListen.get_addr_in();
|
||||
|
||||
m_hListen = m_SessionPolicy.GetSocketFactory().CreateListenSocket(
|
||||
(0 != addr_in.sin_addr.S_un.S_addr) ? inet_ntoa(addr_in.sin_addr) : 0,
|
||||
addrListen.get_port_in());
|
||||
|
||||
if(SOCKET_ERROR == m_hListen)
|
||||
{
|
||||
ERRLOG1(g_SessionLog, "CListener initialized failed : Create listen socket failed : %d",
|
||||
WSAGetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Handler<65><72> Attach<63>Ѵ<EFBFBD>.
|
||||
if(!m_SocketHandler.AttachToHander(
|
||||
reinterpret_cast<HANDLE>(m_hListen), reinterpret_cast<ULONG_PTR>(this)))
|
||||
{
|
||||
ERRLOG1(g_SessionLog, "CListener initialized failed : Attach to Handler failed : %d",
|
||||
WSAGetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pending<6E><67> <20> <20><> <20><><EFBFBD>´<EFBFBD>.
|
||||
if(m_dwMaxPending < dwMaxPending)
|
||||
{
|
||||
m_dwMaxPending = dwMaxPending;
|
||||
}
|
||||
|
||||
dwMaxPending = m_dwMaxPending;
|
||||
}
|
||||
|
||||
for(unsigned long dwCount = 0; dwCount < dwMaxPending; ++dwCount)
|
||||
{
|
||||
PendingAccept();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CListener::InternalCloseListen()
|
||||
{
|
||||
if(INVALID_SOCKET != m_hListen)
|
||||
{
|
||||
if(SOCKET_ERROR == closesocket(m_hListen))
|
||||
{
|
||||
ERRLOG1(g_SessionLog, "closesocket failed : %d", WSAGetLastError());
|
||||
}
|
||||
|
||||
m_hListen = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
void CListener::WaitForPendingComplete(unsigned long dwTime)
|
||||
{
|
||||
unsigned long dwStartTime = timeGetTime();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
long diffTime = timeGetTime() - dwStartTime;
|
||||
|
||||
if(dwTime < static_cast<unsigned long>(std::abs(diffTime)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
if(0 == m_dwCurrentPending)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
bool CListener::PendingAccept()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
|
||||
if(INVALID_SOCKET == m_hListen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long dwAddressLen = sizeof(SOCKADDR_IN) + 16;
|
||||
unsigned long dwBytesReceived = 0;
|
||||
|
||||
SOCKET hSocket = m_SessionPolicy.GetSocketFactory().CreateSocket();
|
||||
CBuffer* lpAddrBuffer = CREATE_BUFFER(m_SessionPolicy.GetBufferFactory(), dwAddressLen * 2);
|
||||
COverlapped* lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateAccept(this, hSocket, lpAddrBuffer);
|
||||
|
||||
if(SOCKET_ERROR == AcceptEx(m_hListen, hSocket, lpAddrBuffer->wr_ptr(),
|
||||
0, dwAddressLen, dwAddressLen, &dwBytesReceived, lpOverlapped))
|
||||
{
|
||||
if(WSA_IO_PENDING != WSAGetLastError())
|
||||
{
|
||||
// <20><><EFBFBD>۴<EFBFBD> <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
++m_dwCurrentPending;
|
||||
++m_dwTotalPendingCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CListener::ProcessAccept(BOOL bResult, SOCKET hSocket,
|
||||
CBuffer* lpBuffer, unsigned long dwProcessedBytes)
|
||||
{
|
||||
INET_Addr localAddr;
|
||||
INET_Addr remoteAddr;
|
||||
|
||||
if(bResult)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD> <20>ɼ<EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
if(SOCKET_ERROR == setsockopt(hSocket, SOL_SOCKET,
|
||||
SO_UPDATE_ACCEPT_CONTEXT, (char*)&m_hListen, sizeof(m_hListen)))
|
||||
{
|
||||
bResult = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SOCKADDR* lpLocalAddr = 0;
|
||||
SOCKADDR* lpRemoteAddr = 0;
|
||||
|
||||
int nLocalSockAddrLen = 0;
|
||||
int nRemoteSockAddrLen = 0;
|
||||
|
||||
unsigned long dwAddressLen = sizeof(SOCKADDR_IN) + 16;
|
||||
|
||||
// <20>ּ<EFBFBD> <20>м<EFBFBD> <20><> <20>ּ<EFBFBD> <20><>ü <20><><EFBFBD><EFBFBD>.
|
||||
GetAcceptExSockaddrs(lpBuffer->rd_ptr(), 0, dwAddressLen, dwAddressLen,
|
||||
&lpLocalAddr, &nLocalSockAddrLen, &lpRemoteAddr, &nRemoteSockAddrLen);
|
||||
|
||||
if(0 != lpLocalAddr)
|
||||
{
|
||||
localAddr.set_addr(*lpLocalAddr, nLocalSockAddrLen);
|
||||
}
|
||||
|
||||
if(0 != lpRemoteAddr)
|
||||
{
|
||||
remoteAddr.set_addr(*lpRemoteAddr, nRemoteSockAddrLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bResult && 0 != m_lpValidateConnection
|
||||
&& !(*m_lpValidateConnection)(localAddr, remoteAddr))
|
||||
{
|
||||
bResult = FALSE;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
CSession* lpSession = 0;
|
||||
|
||||
if(bResult)
|
||||
{
|
||||
lpSession = m_SessionMgr.CreateSession(m_SessionPolicy);
|
||||
|
||||
if(0 == lpSession || !lpSession->isValid())
|
||||
{
|
||||
bResult = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(bResult && !m_SocketHandler.AttachToHander(
|
||||
reinterpret_cast<HANDLE>(hSocket),
|
||||
reinterpret_cast<ULONG_PTR>(lpSession)))
|
||||
{
|
||||
bResult = FALSE;
|
||||
}
|
||||
|
||||
if(bResult)
|
||||
{
|
||||
lpSession->Socket(hSocket);
|
||||
lpSession->SetAddress(remoteAddr, localAddr);
|
||||
|
||||
DETLOG3(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ Accept Session Complete.",
|
||||
lpSession, lpSession->GetDispatch(), remoteAddr.get_addr_string());
|
||||
|
||||
lpSession->InternalRecv();
|
||||
|
||||
m_SessionMgr.Add(lpSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SessionMgr.DeleteSession(lpSession);
|
||||
lpSession = 0;
|
||||
|
||||
// pending failed
|
||||
closesocket(hSocket);
|
||||
}
|
||||
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
--m_dwCurrentPending;
|
||||
++m_dwTotalAcceptCompleteCount;
|
||||
}
|
||||
|
||||
PendingAccept();
|
||||
}
|
||||
|
||||
unsigned long CListener::GetPendingAcceptNum()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
return m_dwCurrentPending;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& CListener::PrintStatistics(std::ostream& strm)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_ListenerLock);
|
||||
|
||||
const int MAX_BUFFER = 1024;
|
||||
char szBuffer[MAX_BUFFER];
|
||||
|
||||
int nLen = InternalPrintStatistics(szBuffer, MAX_BUFFER);
|
||||
|
||||
if(0 < nLen)
|
||||
{
|
||||
strm << szBuffer;
|
||||
}
|
||||
|
||||
return strm;
|
||||
}
|
||||
|
||||
|
||||
int CListener::InternalPrintStatistics(char* szBuffer, int nBufferLen)
|
||||
{
|
||||
return _snprintf(szBuffer, nBufferLen,
|
||||
"[ListenSocket:0x%08x][MaxPending:%d][CurrentPending:%d]"
|
||||
"[TotalPendingCount:%d][TotalAcceptCompleteCount:%d]",
|
||||
m_hListen, m_dwMaxPending, m_dwCurrentPending,
|
||||
m_dwTotalPendingCount, m_dwTotalAcceptCompleteCount);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
bool CListener::LogListenerStatus()
|
||||
{
|
||||
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/ListenerLog-%s.txt", szProgramName, szTime);
|
||||
|
||||
fstream logfile(szFileName, ios::out | ios::app);
|
||||
fstream::char_type endline = logfile.widen('\n');
|
||||
|
||||
logfile << szDelimiter << endline;
|
||||
|
||||
SessionSet::iterator pos = m_SessionSet.begin();
|
||||
SessionSet::iterator end = m_SessionSet.end();
|
||||
|
||||
for(; pos != end; ++pos)
|
||||
{
|
||||
CSession* lpSession = *pos;
|
||||
logfile << lpSession << endline;
|
||||
++nStateNum[lpSession->m_cCurrentStatus];
|
||||
}
|
||||
|
||||
logfile << endline << szDelimiter << endline
|
||||
<< "Time : " << szTime << endline << endline
|
||||
<< "UNINITIALIZED : " << nStateNum[CSession::UNINITIALIZED] << endline
|
||||
<< "ACCEPT_PENDING : " << nStateNum[CSession::ACCEPT_PENDING] << endline
|
||||
<< "CONNECTED : " << nStateNum[CSession::CONNECTED] << endline
|
||||
<< "DISCONNECTED : " << nStateNum[CSession::DISCONNECTED] << endline
|
||||
<< "Total : " << m_dwMaxConnections << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
LONG CValidateConnection::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&m_nRefCount);
|
||||
}
|
||||
|
||||
LONG CValidateConnection::Release()
|
||||
{
|
||||
LONG nRefCount = InterlockedDecrement(&m_nRefCount);
|
||||
if(0 == nRefCount)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return nRefCount;
|
||||
}
|
||||
114
Server/RylServerProject/BaseLibrary/Network/Listener/Listener.h
Normal file
114
Server/RylServerProject/BaseLibrary/Network/Listener/Listener.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#ifndef _CLISTENER_H_
|
||||
#define _CLISTENER_H_
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <list>
|
||||
|
||||
#include <boost/pool/object_pool.hpp>
|
||||
|
||||
#include "../../Thread/Lock.h"
|
||||
#include "../Address/INET_Addr.h"
|
||||
|
||||
#pragma comment(lib, "winmm")
|
||||
#pragma comment(lib, "mswsock")
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
class CBuffer;
|
||||
class CSession;
|
||||
class CSessionMgr;
|
||||
class CSessionPolicy;
|
||||
class CSocketFactory;
|
||||
class CCompletionHandler;
|
||||
|
||||
// IP<49><50>, <20><>Ÿ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><>ħ<EFBFBD><C4A7> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
class CValidateConnection
|
||||
{
|
||||
public:
|
||||
|
||||
LONG AddRef();
|
||||
LONG Release();
|
||||
|
||||
virtual bool operator () (INET_Addr& localAddr, INET_Addr& remoteAddr) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
CValidateConnection() : m_nRefCount(1) { }
|
||||
virtual ~CValidateConnection() { }
|
||||
|
||||
private:
|
||||
|
||||
LONG m_nRefCount;
|
||||
};
|
||||
|
||||
class CListener
|
||||
{
|
||||
public:
|
||||
|
||||
CListener(CCompletionHandler& SocketHandler,
|
||||
CSessionPolicy& SessionPolicy,
|
||||
CSessionMgr& SessionMgr,
|
||||
CValidateConnection* lpValidateConnection);
|
||||
|
||||
virtual ~CListener();
|
||||
|
||||
bool Initialize(const char* lpListenAddress, unsigned short usPort,
|
||||
unsigned long dwMaxPending = 0)
|
||||
{
|
||||
return Initialize(INET_Addr(lpListenAddress, usPort), dwMaxPending);
|
||||
}
|
||||
|
||||
bool Initialize(INET_Addr& addrListen, unsigned long dwMaxPending = 0);
|
||||
|
||||
bool PendingAccept();
|
||||
|
||||
void ProcessAccept(BOOL bResult, SOCKET hSocket,
|
||||
CBuffer* lpBuffer, unsigned long dwProcessedBytes);
|
||||
|
||||
unsigned long GetPendingAcceptNum();
|
||||
CSessionPolicy& GetPolicy() { return m_SessionPolicy; }
|
||||
|
||||
friend std::ostream& Log(std::ostream& strm, CListener* lpListener) { return (0 != lpListener) ? lpListener->PrintStatistics(strm) : strm; }
|
||||
friend std::ostream& Log(std::ostream& strm, CListener& Listener) { return Listener.PrintStatistics(strm); }
|
||||
|
||||
private:
|
||||
|
||||
void InternalProcess();
|
||||
void InternalPending();
|
||||
|
||||
void InternalDestroy();
|
||||
void InternalCloseListen();
|
||||
|
||||
void WaitForPendingComplete(unsigned long dwTime);
|
||||
|
||||
std::ostream& PrintStatistics(std::ostream& strm);
|
||||
int InternalPrintStatistics(char* szBuffer, int nBufferLen);
|
||||
|
||||
//---------------------------------------------------
|
||||
typedef CCSLock SessionLock;
|
||||
|
||||
SessionLock m_ListenerLock; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ǵ帱 <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><>.
|
||||
CACHE_PAD(ListenerLockPad, sizeof(SessionLock));
|
||||
|
||||
SOCKET m_hListen;
|
||||
INET_Addr m_ListenAddr;
|
||||
|
||||
CCompletionHandler& m_SocketHandler;
|
||||
CSessionPolicy& m_SessionPolicy;
|
||||
CSessionMgr& m_SessionMgr;
|
||||
|
||||
unsigned long m_dwMaxPending;
|
||||
unsigned long m_dwCurrentPending;
|
||||
unsigned long m_dwTotalPendingCount;
|
||||
unsigned long m_dwTotalAcceptCompleteCount;
|
||||
|
||||
CValidateConnection* m_lpValidateConnection;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
729
Server/RylServerProject/BaseLibrary/Network/Session/Session.cpp
Normal file
729
Server/RylServerProject/BaseLibrary/Network/Session/Session.cpp
Normal file
@@ -0,0 +1,729 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Session.h"
|
||||
#include "../IOCP/Overlapped.h"
|
||||
#include "../IOCP/CompletionHandler.h"
|
||||
#include "../Winsock/SocketFactory.h"
|
||||
#include "../Address/INET_Addr.h"
|
||||
|
||||
#include "../Dispatch/Dispatch.h"
|
||||
#include "../Dispatch/ServerRequest.h"
|
||||
#include "../../Stream/Buffer/Buffer.h"
|
||||
#include "../../Stream/Buffer/BufferFactory.h"
|
||||
|
||||
#include "../../Log/ServerLog.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// SP : SessionPointer
|
||||
// DP : DispatchPointer
|
||||
|
||||
namespace SessionState
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
CONNECTED, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
DISCONNECTED, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD>.
|
||||
MAX_SESSION_STATE
|
||||
};
|
||||
};
|
||||
|
||||
namespace SessionFlag
|
||||
{
|
||||
// 8bit SessionFlag
|
||||
enum Type
|
||||
{
|
||||
CONNECT_CALLED = ( 1 << 0 ), // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
DISCONNECT_PROCESSED = ( 1 << 1 ), // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
SHUTDOWN_CALLED = ( 1 << 2 ), // Shutdown<77><6E> ȣ<><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
SHUTDOWN_PROCESSED = ( 1 << 3 ), // Shutdown ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
|
||||
SUSPEND_RECV = ( 1 << 4 ) // <20>÷<EFBFBD><C3B7>װ<EFBFBD> <20><><EFBFBD>õǾ<C3B5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Recv<63><76> <20><><EFBFBD><EFBFBD>
|
||||
};
|
||||
};
|
||||
|
||||
namespace SessionConst
|
||||
{
|
||||
enum Data
|
||||
{
|
||||
MAX_RECV_BUFFER = 32768
|
||||
};
|
||||
}
|
||||
|
||||
CSession::CSession(CSessionPolicy& SessionPolicy)
|
||||
: m_hSocket(INVALID_SOCKET),
|
||||
m_nRefCount(0),
|
||||
m_SessionPolicy(SessionPolicy),
|
||||
|
||||
m_dwRecvPending(0),
|
||||
m_dwSendPending(0),
|
||||
|
||||
m_cCurrentStatus(SessionState::CONNECTED),
|
||||
m_cFlags(0),
|
||||
m_usPadding(0x4343)
|
||||
{
|
||||
m_SessionPolicy.AddRef();
|
||||
|
||||
m_lpRecvBuffer = CREATE_BUFFER(SessionPolicy.GetBufferFactory(), SessionConst::MAX_RECV_BUFFER);
|
||||
m_lpDispatch = SessionPolicy.GetDispatchFactory().CreateDispatch(*this);
|
||||
}
|
||||
|
||||
|
||||
CSession::~CSession()
|
||||
{
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
InternalCloseSocket();
|
||||
|
||||
SAFE_RELEASE_BUFFER(m_lpRecvBuffer);
|
||||
m_SessionPolicy.GetDispatchFactory().DeleteDispatch(m_lpDispatch);
|
||||
|
||||
m_usPadding = 0x4444;
|
||||
}
|
||||
|
||||
m_SessionPolicy.Release();
|
||||
}
|
||||
|
||||
|
||||
// false <20><><EFBFBD>Ͻ<EFBFBD> Accept Pending<6E><67> <20><>.
|
||||
bool CSession::Process()
|
||||
{
|
||||
if(!m_lpDispatch)
|
||||
{
|
||||
ERRLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/CloseSocket - Failed Dispatch Pointer",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SessionState::Type eState = SessionState::MAX_SESSION_STATE;
|
||||
unsigned char cFlags = 0;
|
||||
|
||||
bool bCloseSocket = false;
|
||||
bool bCallConnected = false;
|
||||
bool bCallDisconnected = false;
|
||||
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
eState = static_cast<SessionState::Type>(m_cCurrentStatus);
|
||||
|
||||
switch(m_cCurrentStatus)
|
||||
{
|
||||
case SessionState::CONNECTED:
|
||||
|
||||
if(SessionFlag::CONNECT_CALLED != (m_cFlags & SessionFlag::CONNECT_CALLED))
|
||||
{
|
||||
bCallConnected = true;
|
||||
m_cFlags |= SessionFlag::CONNECT_CALLED;
|
||||
}
|
||||
|
||||
if (!(m_cFlags & SessionFlag::SUSPEND_RECV) && 0 == m_dwRecvPending)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>´<DEB4>.
|
||||
InternalRecv();
|
||||
}
|
||||
break;
|
||||
|
||||
case SessionState::DISCONNECTED:
|
||||
|
||||
if(SessionFlag::DISCONNECT_PROCESSED != (m_cFlags & SessionFlag::DISCONNECT_PROCESSED))
|
||||
{
|
||||
bCallDisconnected = true;
|
||||
m_Statistics.m_DisconnectedTime = time(0);
|
||||
m_cFlags |= SessionFlag::DISCONNECT_PROCESSED;
|
||||
}
|
||||
else if(INVALID_SOCKET == m_hSocket &&
|
||||
0 == m_dwRecvPending &&
|
||||
0 == m_dwSendPending &&
|
||||
0 == m_nRefCount)
|
||||
{
|
||||
InternalCloseSocket();
|
||||
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/Eliminate Session",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cFlags = m_cFlags;
|
||||
|
||||
++m_nRefCount;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><>.
|
||||
if(bCallConnected)
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/Connection Open - Process connected",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
m_lpDispatch->Connected();
|
||||
|
||||
m_Statistics.m_ConnectedTime = time(0);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> Dispatch<63><68>.
|
||||
if(SessionState::CONNECTED == eState && !m_lpDispatch->Dispatch())
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/CloseSocket - Failed Dispatch",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
bCloseSocket = true;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20>ݱ<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><>.
|
||||
if(bCallDisconnected)
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Connection Closed - Process disconnect",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
m_lpDispatch->Disconnected();
|
||||
}
|
||||
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
|
||||
InternalSend();
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Shutdown<77><6E> ȣ<><C8A3><EFBFBD>߾<EFBFBD><DFBE><EFBFBD><EFBFBD><EFBFBD> Shutdown ó<><C3B3><EFBFBD><EFBFBD> <20><>.
|
||||
if((m_cFlags & SessionFlag::SHUTDOWN_CALLED) &&
|
||||
m_SendQueue.empty() && INVALID_SOCKET != m_hSocket)
|
||||
{
|
||||
if(shutdown(m_hSocket, SD_SEND))
|
||||
{
|
||||
m_cFlags |= SessionFlag::SHUTDOWN_PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
--m_nRefCount;
|
||||
|
||||
if(bCloseSocket)
|
||||
{
|
||||
InternalCloseSocket();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CSession::Dispatch(unsigned long dwReceivedBytes)
|
||||
{
|
||||
// <20><>Ŷ ó<><C3B3><EFBFBD><EFBFBD> <20>ϰ<EFBFBD>, ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>δ<EFBFBD>.
|
||||
m_lpRecvBuffer->wr_ptr(dwReceivedBytes);
|
||||
unsigned long dwDispatchSize = static_cast<unsigned long>(m_lpRecvBuffer->length());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> 0(<28><><EFBFBD><EFBFBD> <20>Ϸ<EFBFBD>) <20>̰ų<CCB0>, <20><>Ŷ ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> Socket<65><74> Close<73>Ѵ<EFBFBD>.
|
||||
bool bResult = (0 != dwReceivedBytes &&
|
||||
m_lpDispatch->ParsePacket(m_lpRecvBuffer->rd_ptr(), &dwDispatchSize));
|
||||
|
||||
m_lpRecvBuffer->rd_ptr(dwDispatchSize);
|
||||
m_lpRecvBuffer->pop_read_data();
|
||||
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
m_Statistics.m_dwTotalReceived += dwReceivedBytes;
|
||||
--m_dwRecvPending;
|
||||
|
||||
if (!bResult)
|
||||
{
|
||||
DETLOG7(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/shutdown - %s : dwReceivedBytes:%d, ErrorCode:%d",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket,
|
||||
(0 == dwReceivedBytes) ? "Disconnected" : "Failed To Dispatch Packet",
|
||||
dwReceivedBytes, WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void CSession::InternalCloseSocket()
|
||||
{
|
||||
if(INVALID_SOCKET != m_hSocket)
|
||||
{
|
||||
const char* szRemoteAddr = m_RemoteAddr.get_addr_string();
|
||||
|
||||
if(SOCKET_ERROR == shutdown(m_hSocket, SD_SEND))
|
||||
{
|
||||
DETLOG5(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Shutdown failed - ErrorCode:%d",
|
||||
this, m_lpDispatch, szRemoteAddr, m_hSocket, WSAGetLastError());
|
||||
}
|
||||
|
||||
if(SOCKET_ERROR == closesocket(m_hSocket))
|
||||
{
|
||||
DETLOG5(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket failed - ErrorCode:%d",
|
||||
this, m_lpDispatch, szRemoteAddr, m_hSocket, WSAGetLastError());
|
||||
}
|
||||
|
||||
const int MAX_BUFFER = 1024;
|
||||
char szBuffer[MAX_BUFFER];
|
||||
|
||||
if(0 < InternalPrintStatistics(szBuffer, MAX_BUFFER))
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ InternalCloseSocket - Statistics : %s",
|
||||
this, m_lpDispatch, szRemoteAddr, szBuffer);
|
||||
}
|
||||
|
||||
m_cFlags |= SessionFlag::SHUTDOWN_PROCESSED;
|
||||
m_hSocket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
m_cCurrentStatus = SessionState::DISCONNECTED;
|
||||
}
|
||||
|
||||
|
||||
bool CSession::Shutdown()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
m_cFlags |= SessionFlag::SHUTDOWN_CALLED;
|
||||
return false;
|
||||
}
|
||||
|
||||
LONG CSession::AddRef()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
return ++m_nRefCount;
|
||||
}
|
||||
|
||||
|
||||
LONG CSession::Release()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
return --m_nRefCount;
|
||||
}
|
||||
|
||||
|
||||
void CSession::CloseSession()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ InternalCloseSocket - SessionClose Called : %d",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
}
|
||||
|
||||
|
||||
bool CSession::IsConnected()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
return (SessionState::CONNECTED == m_cCurrentStatus && m_hSocket != INVALID_SOCKET);
|
||||
}
|
||||
|
||||
|
||||
bool CSession::CalledConnected()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
return SessionFlag::CONNECT_CALLED == (m_cFlags & SessionFlag::CONNECT_CALLED);
|
||||
}
|
||||
|
||||
bool CSession::CalledDisconnected()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
return SessionFlag::DISCONNECT_PROCESSED == (m_cFlags & SessionFlag::DISCONNECT_PROCESSED);
|
||||
}
|
||||
|
||||
void CSession::SendCompleted(BOOL bResult, unsigned long dwSendedBytes)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
--m_dwSendPending;
|
||||
m_Statistics.m_dwTotalSendCompleted += dwSendedBytes;
|
||||
|
||||
if(!bResult)
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ InternalCloseSocket - Send Completion Error : %d",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalSend();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSession::SetAddress(INET_Addr& remoteAddr, INET_Addr& localAddr)
|
||||
{
|
||||
m_RemoteAddr = remoteAddr;
|
||||
m_LocalAddr = localAddr;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& CSession::PrintStatistics(std::ostream& strm)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
const int MAX_BUFFER = 1024;
|
||||
char szBuffer[MAX_BUFFER];
|
||||
|
||||
int nLen = InternalPrintStatistics(szBuffer, MAX_BUFFER);
|
||||
|
||||
if(0 < nLen)
|
||||
{
|
||||
strm << szBuffer;
|
||||
}
|
||||
|
||||
return strm;
|
||||
}
|
||||
|
||||
|
||||
int CSession::InternalPrintStatistics(char* szBuffer, int nBufferLen)
|
||||
{
|
||||
const char* szMode = 0;
|
||||
|
||||
switch(m_cCurrentStatus)
|
||||
{
|
||||
case SessionState::CONNECTED: szMode = "CONNECTED"; break;
|
||||
case SessionState::DISCONNECTED: szMode = "DISCONNECTED"; break;
|
||||
default: szMode = "Unknown Mode"; break;
|
||||
}
|
||||
|
||||
int nLen = _snprintf(szBuffer, nBufferLen - 1,
|
||||
"[m_hSocket:0x%08x][%15s][DiffTime(Sec):%8f]"
|
||||
"[m_dwTotalReceived:%5d][m_dwTotalSendPending:%5d][m_dwTotalSendCompleted:%5d]"
|
||||
"[m_dwSendPending:%d][m_dwRecvPending:%d][m_nRefCount:%2d][flags:0x%02x]",
|
||||
|
||||
m_hSocket, szMode, difftime(time(0), m_Statistics.m_ConnectedTime),
|
||||
m_Statistics.m_dwTotalReceived, m_Statistics.m_dwTotalSendPending,
|
||||
m_Statistics.m_dwTotalSendCompleted,
|
||||
m_dwSendPending, m_dwRecvPending,
|
||||
m_nRefCount, m_cFlags);
|
||||
|
||||
szBuffer[nBufferLen - 1] = 0;
|
||||
return nLen;
|
||||
}
|
||||
|
||||
|
||||
bool CSession::InternalRecv()
|
||||
{
|
||||
if (m_cFlags & SessionFlag::SUSPEND_RECV)
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Recv suspending now",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (0 != m_dwRecvPending)
|
||||
{
|
||||
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Recv pending now",
|
||||
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long dwReceived = 0;
|
||||
unsigned long dwFlags = 0;
|
||||
|
||||
WSABUF wsaBuf;
|
||||
|
||||
wsaBuf.buf = m_lpRecvBuffer->wr_ptr();
|
||||
wsaBuf.len = static_cast<u_long>(m_lpRecvBuffer->remain());
|
||||
|
||||
COverlapped* lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateRecv(this, m_lpRecvBuffer);
|
||||
|
||||
const char* lpErrorFmtString = 0;
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
if(SOCKET_ERROR == WSARecv(m_hSocket, &wsaBuf, 1,
|
||||
&dwReceived, &dwFlags, lpOverlapped, 0))
|
||||
{
|
||||
if(WSA_IO_PENDING != WSAGetLastError())
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/InternalCloseSocket"
|
||||
" - WSARecv Error - ErrorCode:%d";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/InternalCloseSocket"
|
||||
" - WSARecv Error - Create RecvOverlapped Failed - ErrorCode:%d";
|
||||
}
|
||||
|
||||
if(0 != lpErrorFmtString)
|
||||
{
|
||||
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
|
||||
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
|
||||
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
|
||||
return false;
|
||||
}
|
||||
|
||||
++m_dwRecvPending;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CSession::InternalRecvFrom()
|
||||
{
|
||||
if(0 != m_dwRecvPending)
|
||||
{
|
||||
//DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ RecvFrom pending now",
|
||||
// this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(INVALID_SOCKET == m_hSocket)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long dwReceived = 0;
|
||||
unsigned long dwFlags = 0;
|
||||
|
||||
WSABUF wsaBuf;
|
||||
|
||||
wsaBuf.buf = m_lpRecvBuffer->wr_ptr();
|
||||
wsaBuf.len = static_cast<u_long>(m_lpRecvBuffer->remain());
|
||||
|
||||
COverlapped* lpOverlapped =
|
||||
m_SessionPolicy.GetOverlappedFactory().CreateRecv(this, m_lpRecvBuffer);
|
||||
|
||||
const char* lpErrorFmtString = 0;
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
INET_Addr& addr = m_lpRecvBuffer->get_addr();
|
||||
|
||||
if(SOCKET_ERROR == WSARecvFrom(m_hSocket, &wsaBuf, 1, &dwReceived, &dwFlags,
|
||||
&addr.get_addr(), addr.get_size_ptr(), lpOverlapped, 0))
|
||||
{
|
||||
if(WSA_IO_PENDING != WSAGetLastError())
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
|
||||
" - WSARecvFrom Error - ErrorCode:%d";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/InternalCloseSocket"
|
||||
" - WSARecvFrom Error - Create RecvOverlapped Failed - ErrorCode:%d";
|
||||
}
|
||||
|
||||
if(0 != lpErrorFmtString)
|
||||
{
|
||||
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
|
||||
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
++m_dwRecvPending;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CSession::SendResult CSession::InternalSend(CBuffer* lpBuffer)
|
||||
{
|
||||
if(0 != m_dwSendPending)
|
||||
{
|
||||
return SEND_NEXT_TURN;
|
||||
}
|
||||
|
||||
if(INVALID_SOCKET == m_hSocket)
|
||||
{
|
||||
return SEND_FAILED;
|
||||
}
|
||||
|
||||
const char* lpErrorFmtString = 0;
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateSend(this, lpBuffer);
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
unsigned long dwSentBytes = 0;
|
||||
|
||||
WSABUF wsaBuf;
|
||||
|
||||
wsaBuf.buf = lpBuffer->rd_ptr();
|
||||
wsaBuf.len = static_cast<u_long>(lpBuffer->length());
|
||||
|
||||
m_Statistics.m_dwTotalSendPending += wsaBuf.len;
|
||||
|
||||
if(SOCKET_ERROR == WSASend(m_hSocket, &wsaBuf, 1,
|
||||
&dwSentBytes, 0, lpOverlapped, 0))
|
||||
{
|
||||
if(WSA_IO_PENDING != WSAGetLastError())
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ "
|
||||
"InternalCloseSocket - WSASend Error - ErrorCode:%d";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
|
||||
" - WSASend Error - Cannot Create SendOverlapped - ErrorCode:%d";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
|
||||
" - WSASend Error - lpBuffer is 0 - ErrorCode:%d";
|
||||
}
|
||||
|
||||
if(0 != lpErrorFmtString)
|
||||
{
|
||||
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
|
||||
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
lpOverlapped->SetBuffer(0);
|
||||
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
|
||||
}
|
||||
|
||||
return SEND_FAILED;
|
||||
}
|
||||
|
||||
++m_dwSendPending;
|
||||
return SEND_SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CSession::SendResult CSession::InternalSendTo(CBuffer* lpBuffer)
|
||||
{
|
||||
if(0 != m_dwSendPending)
|
||||
{
|
||||
return SEND_NEXT_TURN;
|
||||
}
|
||||
|
||||
if(INVALID_SOCKET == m_hSocket)
|
||||
{
|
||||
return SEND_FAILED;
|
||||
}
|
||||
|
||||
const char* lpErrorFmtString = 0;
|
||||
COverlapped* lpOverlapped = 0;
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateSend(this, lpBuffer);
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
unsigned long dwSentBytes = 0;
|
||||
|
||||
WSABUF wsaBuf;
|
||||
|
||||
wsaBuf.buf = lpBuffer->rd_ptr();
|
||||
wsaBuf.len = static_cast<u_long>(lpBuffer->length());
|
||||
|
||||
m_Statistics.m_dwTotalSendPending += wsaBuf.len;
|
||||
|
||||
INET_Addr& addr = lpBuffer->get_addr();
|
||||
|
||||
if(SOCKET_ERROR == WSASendTo(m_hSocket, &wsaBuf, 1,
|
||||
&dwSentBytes, 0, &addr.get_addr(), addr.get_size(), lpOverlapped, 0))
|
||||
{
|
||||
if(WSA_IO_PENDING != WSAGetLastError())
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ "
|
||||
"InternalCloseSocket - WSASendTo Error - ErrorCode:%d";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
|
||||
" - WSASendTo Error - Cannot Create SendOverlapped - ErrorCode:%d";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
|
||||
" - WSASendTo Error - lpBuffer is 0 - ErrorCode:%d";
|
||||
}
|
||||
|
||||
if(0 != lpErrorFmtString)
|
||||
{
|
||||
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
|
||||
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
|
||||
|
||||
InternalCloseSocket();
|
||||
|
||||
if(0 != lpOverlapped)
|
||||
{
|
||||
lpOverlapped->SetBuffer(0);
|
||||
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
|
||||
}
|
||||
|
||||
return SEND_FAILED;
|
||||
}
|
||||
|
||||
++m_dwSendPending;
|
||||
return SEND_SUCCEEDED;
|
||||
}
|
||||
|
||||
bool CSession::SendPending(CBuffer* lpBuffer)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
|
||||
if(!(SessionFlag::SHUTDOWN_CALLED & m_cFlags) && INVALID_SOCKET != m_hSocket)
|
||||
{
|
||||
m_SendQueue.enqueue(lpBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSession::InternalSend()
|
||||
{
|
||||
SendResult eSendResult = SEND_SUCCEEDED;
|
||||
|
||||
if(0 == m_dwSendPending)
|
||||
{
|
||||
CBuffer* lpBuffer = m_SendQueue.dequeue();
|
||||
|
||||
if(0 != lpBuffer)
|
||||
{
|
||||
eSendResult = (0 == lpBuffer->get_addr().get_size()) ?
|
||||
InternalSend(lpBuffer) : InternalSendTo(lpBuffer);
|
||||
|
||||
if(SEND_SUCCEEDED != eSendResult)
|
||||
{
|
||||
m_SendQueue.enqueue(lpBuffer, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (SEND_FAILED != eSendResult);
|
||||
}
|
||||
|
||||
void CSession::SuspendRecv()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
m_cFlags |= SessionFlag::SUSPEND_RECV;
|
||||
}
|
||||
|
||||
void CSession::ResumeRecv()
|
||||
{
|
||||
SessionLock::Syncronize sync(m_SessionLock);
|
||||
m_cFlags &= ~SessionFlag::SUSPEND_RECV;
|
||||
}
|
||||
159
Server/RylServerProject/BaseLibrary/Network/Session/Session.h
Normal file
159
Server/RylServerProject/BaseLibrary/Network/Session/Session.h
Normal file
@@ -0,0 +1,159 @@
|
||||
#ifndef _CSESSION_H_
|
||||
#define _CSESSION_H_
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <mswsock.h>
|
||||
#include <iosfwd>
|
||||
|
||||
#include "SessionPolicy.h"
|
||||
|
||||
#include "../Address/INET_Addr.h"
|
||||
#include "../IOCP/Overlapped.h"
|
||||
#include "../../Thread/Lock.h"
|
||||
#include "../../Stream/Buffer/BufferQueue.h"
|
||||
|
||||
#pragma comment(lib, "ws2_32")
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
class CBuffer;
|
||||
class CBufferFactory;
|
||||
|
||||
class CPacketDispatch;
|
||||
class CDispatchFactory;
|
||||
|
||||
class CCompletionHandler;
|
||||
class CSocketBaseFactory;
|
||||
|
||||
|
||||
struct SessionStatistics
|
||||
{
|
||||
unsigned long m_dwTotalReceived; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>.
|
||||
unsigned long m_dwTotalSendPending; // <20><><EFBFBD>ǿ<EFBFBD><C7BF><EFBFBD> pending<6E><67> <20><>.
|
||||
unsigned long m_dwTotalSendCompleted; // Send<6E>Ϸ<EFBFBD><CFB7><EFBFBD> <20><>.
|
||||
time_t m_ConnectedTime; // Connect<63><74> <20>ð<EFBFBD>.
|
||||
time_t m_DisconnectedTime; // Disconnected<65><64> <20>ð<EFBFBD>.
|
||||
|
||||
SessionStatistics::SessionStatistics()
|
||||
: m_dwTotalReceived(0), m_dwTotalSendPending(0), m_dwTotalSendCompleted(0),
|
||||
m_ConnectedTime(0), m_DisconnectedTime(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
m_dwTotalReceived = m_dwTotalSendPending = m_dwTotalSendCompleted = 0;
|
||||
m_ConnectedTime = m_DisconnectedTime = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CSession
|
||||
{
|
||||
public:
|
||||
|
||||
CSession(CSessionPolicy& SessionPolicy);
|
||||
~CSession();
|
||||
|
||||
enum SendResult
|
||||
{
|
||||
SEND_SUCCEEDED,
|
||||
SEND_FAILED,
|
||||
SEND_NEXT_TURN,
|
||||
};
|
||||
|
||||
LONG AddRef();
|
||||
LONG Release();
|
||||
|
||||
bool IsConnected();
|
||||
void CloseSession();
|
||||
|
||||
bool CalledConnected();
|
||||
bool CalledDisconnected();
|
||||
|
||||
void SetAddress(INET_Addr& remoteAddr, INET_Addr& localAddr);
|
||||
INET_Addr& GetRemoteAddr() { return m_RemoteAddr; }
|
||||
INET_Addr& GetLocalAddr() { return m_LocalAddr; }
|
||||
|
||||
CPacketDispatch* GetDispatch() { return m_lpDispatch; }
|
||||
CSessionPolicy& GetPolicy() { return m_SessionPolicy; }
|
||||
|
||||
const SessionStatistics& GetStatistics() { return m_Statistics; }
|
||||
|
||||
bool SendPending(CBuffer* lpBuffer);
|
||||
void SendCompleted(BOOL bResult, unsigned long dwSendedBytes);
|
||||
|
||||
bool Process();
|
||||
bool Dispatch(unsigned long dwReceivedBytes);
|
||||
|
||||
bool Recv() { SessionLock::Syncronize sync(m_SessionLock); return InternalRecv(); }
|
||||
bool RecvFrom() { SessionLock::Syncronize sync(m_SessionLock); return InternalRecvFrom(); }
|
||||
bool Send() { SessionLock::Syncronize sync(m_SessionLock); return InternalSend(); }
|
||||
|
||||
bool Connect(CCompletionHandler& Handler, LPSTR lpConnectAddress, unsigned short usPort);
|
||||
bool Shutdown();
|
||||
|
||||
void SuspendRecv();
|
||||
void ResumeRecv();
|
||||
|
||||
friend std::ostream& Log(std::ostream& strm, CSession* lpSession) { return (0 != lpSession) ? lpSession->PrintStatistics(strm) : strm; }
|
||||
friend std::ostream& Log(std::ostream& strm, CSession& Session) { return Session.PrintStatistics(strm); }
|
||||
|
||||
private:
|
||||
|
||||
bool isValid() const { return (0 != m_lpRecvBuffer && 0 != m_lpDispatch); }
|
||||
void Socket(SOCKET hSocket) { m_hSocket = hSocket; }
|
||||
SOCKET Socket() { return m_hSocket; }
|
||||
|
||||
bool InternalRecv();
|
||||
bool InternalRecvFrom();
|
||||
|
||||
bool InternalSend();
|
||||
SendResult InternalSend(CBuffer* lpBuffer);
|
||||
SendResult InternalSendTo(CBuffer* lpBuffer);
|
||||
|
||||
void InternalCloseSocket();
|
||||
|
||||
// Desc : <20>α<EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
std::ostream& PrintStatistics(std::ostream& strm);
|
||||
int InternalPrintStatistics(char* szBuffer, int nBufferLen);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
typedef CCSLock SessionLock; // Critical Section Lock (24byte)
|
||||
|
||||
SessionLock m_SessionLock; // Multithreadȯ<64><C8AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Lock
|
||||
CACHE_PAD(LockPadding, sizeof(SessionLock));// Cache-align<67><6E> <20><><EFBFBD><EFBFBD> Padding
|
||||
|
||||
// Shared class
|
||||
CSessionPolicy& m_SessionPolicy; // Session Policy
|
||||
|
||||
// Per-session data
|
||||
CPacketDispatch* m_lpDispatch; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PacketDispatchŬ<68><C5AC><EFBFBD><EFBFBD>
|
||||
|
||||
SOCKET m_hSocket; // Socket Descriptor
|
||||
|
||||
INET_Addr m_RemoteAddr; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ּ<EFBFBD>
|
||||
INET_Addr m_LocalAddr; // <20><><EFBFBD><EFBFBD> <20>ּ<EFBFBD>
|
||||
|
||||
CBuffer* m_lpRecvBuffer; // Recv Buffer
|
||||
CBufferQueue m_SendQueue; // SendQueue
|
||||
|
||||
unsigned long m_dwRecvPending; // Recv PendingCount
|
||||
unsigned long m_dwSendPending; // Send PendingCount
|
||||
|
||||
LONG m_nRefCount; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD>۷<EFBFBD><DBB7><EFBFBD> ī<><C4AB>Ʈ
|
||||
|
||||
SessionStatistics m_Statistics; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
unsigned char m_cCurrentStatus; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
unsigned char m_cFlags; // <20><><EFBFBD><EFBFBD> flag
|
||||
unsigned short m_usPadding; // <20>е<EFBFBD><D0B5><EFBFBD>
|
||||
|
||||
friend class CListener;
|
||||
friend class CIOCPNet;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "SessionMgr.h"
|
||||
#include "Session.h"
|
||||
|
||||
#include <boost/pool/object_pool.hpp>
|
||||
|
||||
CSessionMgr::CSessionMgr()
|
||||
: m_lpSessionPool(new boost::pool<>(sizeof(CSession)))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CSessionMgr::~CSessionMgr()
|
||||
{
|
||||
// <20><>Ÿ <20><><EFBFBD><EFBFBD><EFBFBD>۾<EFBFBD>.
|
||||
Destroy(5000);
|
||||
|
||||
delete m_lpSessionPool;
|
||||
}
|
||||
|
||||
void CSessionMgr::Add(CSession* lpSession)
|
||||
{
|
||||
if(0 != lpSession)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_AddLock);
|
||||
m_to_be_added.push_back(lpSession);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSessionMgr::InternalProcess()
|
||||
{
|
||||
{
|
||||
SessionLock::Syncronize sync(m_AddLock);
|
||||
m_current.splice(m_current.end(), m_to_be_added);
|
||||
}
|
||||
|
||||
SessionSet::iterator pos = m_current.begin();
|
||||
SessionSet::iterator end = m_current.end();
|
||||
|
||||
CSession* lpSession = 0;
|
||||
|
||||
for(;pos != end;)
|
||||
{
|
||||
lpSession = *pos;
|
||||
|
||||
if(!lpSession->Process())
|
||||
{
|
||||
pos = m_current.erase(pos);
|
||||
DeleteSession(lpSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSessionMgr::Destroy(unsigned long dwWaitTime)
|
||||
{
|
||||
SessionLock::Syncronize process_sync(m_ProcessLock);
|
||||
|
||||
{
|
||||
SessionLock::Syncronize sync(m_AddLock);
|
||||
m_current.splice(m_current.end(), m_to_be_added);
|
||||
}
|
||||
|
||||
SessionSet::iterator pos = m_current.begin();
|
||||
SessionSet::iterator end = m_current.end();
|
||||
|
||||
CSession* lpSession = 0;
|
||||
|
||||
for(;pos != end; ++pos)
|
||||
{
|
||||
lpSession = *pos;
|
||||
lpSession->CloseSession();
|
||||
}
|
||||
|
||||
pos = m_current.begin();
|
||||
end = m_current.end();
|
||||
|
||||
unsigned long dwTime = timeGetTime();
|
||||
|
||||
while(!m_current.empty()
|
||||
&& timeGetTime() < dwTime + dwWaitTime)
|
||||
{
|
||||
InternalProcess();
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSession* CSessionMgr::CreateSession(CSessionPolicy& SessionPolicy)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_CreationLock);
|
||||
|
||||
void* ptr = m_lpSessionPool->malloc();
|
||||
|
||||
return ptr ? new (ptr) CSession(SessionPolicy) : 0;
|
||||
}
|
||||
|
||||
|
||||
void CSessionMgr::DeleteSession(CSession* lpSession)
|
||||
{
|
||||
SessionLock::Syncronize sync(m_CreationLock);
|
||||
|
||||
if(0 != m_lpSessionPool && 0 != lpSession)
|
||||
{
|
||||
lpSession->~CSession();
|
||||
m_lpSessionPool->free(lpSession);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef _NETWORK_SESSION_MGR_H_
|
||||
#define _NETWORK_SESSION_MGR_H_
|
||||
|
||||
#include "../../Thread/Lock.h"
|
||||
|
||||
#include <list>
|
||||
#include <boost/pool/poolfwd.hpp>
|
||||
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
class CSession;
|
||||
class CSessionPolicy;
|
||||
|
||||
class CSessionMgr
|
||||
{
|
||||
public:
|
||||
|
||||
CSessionMgr();
|
||||
~CSessionMgr();
|
||||
|
||||
void Add(CSession* lpSession);
|
||||
void Process() { SessionLock::Syncronize process_sync(m_ProcessLock); InternalProcess(); }
|
||||
void Destroy(unsigned long dwWaitTime = INFINITE);
|
||||
|
||||
size_t GetSessionNum() { SessionLock::Syncronize process_sync(m_ProcessLock); return m_current.size(); }
|
||||
|
||||
CSession* CreateSession(CSessionPolicy& SessionPolicy);
|
||||
void DeleteSession(CSession* lpSession);
|
||||
|
||||
private:
|
||||
|
||||
void InternalProcess();
|
||||
|
||||
typedef CCSLock SessionLock;
|
||||
typedef std::list<CSession*> SessionSet;
|
||||
|
||||
SessionLock m_AddLock;
|
||||
SessionSet m_to_be_added;
|
||||
|
||||
CACHE_PAD(AddLockPad, sizeof(SessionSet));
|
||||
|
||||
SessionLock m_ProcessLock;
|
||||
SessionSet m_current;
|
||||
|
||||
CACHE_PAD(ProcessLockPad, sizeof(SessionSet));
|
||||
|
||||
SessionLock m_CreationLock;
|
||||
boost::pool<>* m_lpSessionPool;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "stdafx.h"
|
||||
#include "SessionPolicy.h"
|
||||
|
||||
#include "../IOCP/Overlapped.h"
|
||||
#include "../Dispatch/Dispatch.h"
|
||||
#include "../Winsock/SocketFactory.h"
|
||||
#include "../../Stream/Buffer/BufferFactory.h"
|
||||
|
||||
CSessionPolicy::CSessionPolicy(CSocketFactory* lpSocketFactory,
|
||||
CBufferFactory* lpBufferFactory,
|
||||
CDispatchFactory* lpDispatchFactory,
|
||||
COverlappedFactory* lpOverlappedFactory)
|
||||
: m_lpSocketFactory(lpSocketFactory),
|
||||
m_lpBufferFactory(lpBufferFactory),
|
||||
m_lpDispatchFactory(lpDispatchFactory),
|
||||
m_lpOverlappedFactory(lpOverlappedFactory),
|
||||
m_nRefCount(1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CSessionPolicy::~CSessionPolicy()
|
||||
{
|
||||
delete m_lpSocketFactory;
|
||||
delete m_lpBufferFactory;
|
||||
delete m_lpDispatchFactory;
|
||||
delete m_lpOverlappedFactory;
|
||||
}
|
||||
|
||||
|
||||
LONG CSessionPolicy::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&m_nRefCount);
|
||||
}
|
||||
|
||||
LONG CSessionPolicy::Release()
|
||||
{
|
||||
LONG nRefCount = InterlockedDecrement(&m_nRefCount);
|
||||
if(0 == nRefCount)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return nRefCount;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef _GAMA_NETWORK_LIBRARY_SESSION_POLICY_H_
|
||||
#define _GAMA_NETWORK_LIBRARY_SESSION_POLICY_H_
|
||||
|
||||
// forward decl.
|
||||
class CSocketFactory;
|
||||
class CBufferFactory;
|
||||
class CDispatchFactory;
|
||||
class COverlappedFactory;
|
||||
|
||||
class CSessionPolicy
|
||||
{
|
||||
public:
|
||||
|
||||
LONG AddRef();
|
||||
LONG Release();
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
return 0 != m_lpBufferFactory && 0 != m_lpSocketFactory &&
|
||||
0 != m_lpDispatchFactory && 0 != m_lpOverlappedFactory;
|
||||
}
|
||||
|
||||
CSocketFactory& GetSocketFactory() { return *m_lpSocketFactory; }
|
||||
CBufferFactory& GetBufferFactory() { return *m_lpBufferFactory; }
|
||||
CDispatchFactory& GetDispatchFactory() { return *m_lpDispatchFactory; }
|
||||
COverlappedFactory& GetOverlappedFactory() { return *m_lpOverlappedFactory; }
|
||||
|
||||
// Creation Factory
|
||||
template <class SocketFactory, class BufferFactory, class DispatchFactory, class OverlappedFactory>
|
||||
static CSessionPolicy* Create()
|
||||
{
|
||||
CSessionPolicy* lpSessionPolicy = new (std::nothrow) CSessionPolicy(
|
||||
new SocketFactory,
|
||||
new BufferFactory,
|
||||
new DispatchFactory,
|
||||
new OverlappedFactory);
|
||||
|
||||
if(0 == lpSessionPolicy || !lpSessionPolicy->IsValid())
|
||||
{
|
||||
delete lpSessionPolicy;
|
||||
lpSessionPolicy = 0;
|
||||
}
|
||||
|
||||
return lpSessionPolicy;
|
||||
}
|
||||
|
||||
// edith 2009.08.14 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><DEB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Private Ÿ<>Կ<EFBFBD><D4BF><EFBFBD> Public Ÿ<><C5B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
~CSessionPolicy();
|
||||
|
||||
private:
|
||||
|
||||
CSessionPolicy(
|
||||
CSocketFactory* lpSocketFactory,
|
||||
CBufferFactory* lpBufferFactory,
|
||||
CDispatchFactory* lpDispatchFactory,
|
||||
COverlappedFactory* lpOverlappedFactory);
|
||||
|
||||
|
||||
CSocketFactory* m_lpSocketFactory;
|
||||
CBufferFactory* m_lpBufferFactory;
|
||||
CDispatchFactory* m_lpDispatchFactory;
|
||||
COverlappedFactory* m_lpOverlappedFactory;
|
||||
LONG m_nRefCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,280 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <wsipx.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "SocketFactory.h"
|
||||
//#include "../../Utility/Math/Math.h"
|
||||
|
||||
|
||||
CSocketFactory::CSocketFactory(int nSocketFamily, int nSocketType, int nSocketProtocol, int nAddressLen)
|
||||
: m_nSockFamily(nSocketFamily), m_nSockType(nSocketType), m_nSockProtocol(nSocketProtocol),
|
||||
m_nAddressLen(nAddressLen)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CINETFamilyFactory::CINETFamilyFactory(int nSocketType, int nSocketProtocol)
|
||||
: CSocketFactory(AF_INET, nSocketType, nSocketProtocol, sizeof(SOCKADDR_IN))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CTCPFactory::CTCPFactory()
|
||||
: CINETFamilyFactory(SOCK_STREAM, IPPROTO_TCP)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CUDPFactory::CUDPFactory()
|
||||
: CINETFamilyFactory(SOCK_DGRAM, IPPROTO_UDP)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CIPXFamilyFactory::CIPXFamilyFactory(int nSocketType, int nSocketProtocol)
|
||||
: CSocketFactory(AF_IPX, nSocketType, nSocketProtocol, sizeof(SOCKADDR_IPX))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CSPXFactory::CSPXFactory()
|
||||
: CIPXFamilyFactory(SOCK_STREAM, NSPROTO_SPX)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
CIPXFactory::CIPXFactory()
|
||||
: CIPXFamilyFactory(SOCK_DGRAM, NSPROTO_IPX)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
SOCKET CSocketFactory::CreateSocket()
|
||||
{
|
||||
SOCKET hSocket = WSASocket(m_nSockFamily, m_nSockType, m_nSockProtocol,
|
||||
NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||
|
||||
return hSocket;
|
||||
}
|
||||
|
||||
|
||||
SOCKET CSocketFactory::CreateConnectedSocket(const char* lpConnAddr, unsigned short usPort)
|
||||
{
|
||||
SOCKADDR sockAddr;
|
||||
if (!SetAddr(&sockAddr, lpConnAddr, usPort))
|
||||
{
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
SOCKET connectedSocket = CreateSocket();
|
||||
if (INVALID_SOCKET != connectedSocket)
|
||||
{
|
||||
if (SOCKET_ERROR == connect(connectedSocket, &sockAddr, m_nAddressLen))
|
||||
{
|
||||
closesocket(connectedSocket);
|
||||
connectedSocket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
return connectedSocket;
|
||||
}
|
||||
|
||||
|
||||
SOCKET CSocketFactory::CreateBindedSocket(const char* lpBindAddr, unsigned short usPort)
|
||||
{
|
||||
SOCKADDR sockAddr;
|
||||
if (!SetAddr(&sockAddr, lpBindAddr, usPort))
|
||||
{
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
SOCKET bindedSocket = CreateSocket();
|
||||
if(INVALID_SOCKET != bindedSocket)
|
||||
{
|
||||
BOOL bReuseAddr = TRUE;
|
||||
if (SOCKET_ERROR == setsockopt(bindedSocket, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&bReuseAddr, sizeof(bReuseAddr)))
|
||||
{
|
||||
closesocket(bindedSocket);
|
||||
bindedSocket = INVALID_SOCKET;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(SOCKET_ERROR == bind(bindedSocket, &sockAddr, m_nAddressLen))
|
||||
{
|
||||
closesocket(bindedSocket);
|
||||
bindedSocket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bindedSocket;
|
||||
}
|
||||
|
||||
SOCKET CSocketFactory::CreateListenSocket(const char* lpListenAddr, unsigned short usPort, int nBackLog)
|
||||
{
|
||||
nBackLog = min(nBackLog, MAX_BACKLOG);
|
||||
|
||||
// bind server to Server address
|
||||
SOCKET sdListen = CreateBindedSocket(lpListenAddr, usPort);
|
||||
if (INVALID_SOCKET != sdListen)
|
||||
{
|
||||
// start listening
|
||||
if (SOCKET_ERROR == listen(sdListen, nBackLog))
|
||||
{
|
||||
closesocket(sdListen);
|
||||
sdListen = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
return sdListen;
|
||||
}
|
||||
|
||||
|
||||
bool CINETFamilyFactory::SetAddr(LPSOCKADDR lpSA, const char* szAddr, unsigned short usPort)
|
||||
{
|
||||
int nAddrLen = sizeof(SOCKADDR_IN);
|
||||
|
||||
memset(lpSA, 0, nAddrLen);
|
||||
|
||||
LPSOCKADDR_IN lpSA_in = reinterpret_cast<LPSOCKADDR_IN>(lpSA);
|
||||
|
||||
if (0 != szAddr)
|
||||
{
|
||||
lpSA_in->sin_family = m_nSockFamily;
|
||||
lpSA_in->sin_addr.S_un.S_addr = inet_addr(szAddr);
|
||||
lpSA_in->sin_port = htons(usPort);
|
||||
|
||||
if(0 == lpSA_in->sin_addr.S_un.S_addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpSA_in->sin_addr.S_un.S_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
|
||||
lpSA_in->sin_family = m_nSockFamily;
|
||||
lpSA_in->sin_port = htons(usPort);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CINETFamilyFactory::GetNetworkInfo(char *Address_Out, int nMaxBufferSize)
|
||||
{
|
||||
const int MAX_HOSTNAME_BUFFER = 256;
|
||||
char szHostName[MAX_HOSTNAME_BUFFER];
|
||||
if(!gethostname(szHostName, MAX_HOSTNAME_BUFFER - 1))
|
||||
{
|
||||
szHostName[MAX_HOSTNAME_BUFFER - 1] = '\0';
|
||||
|
||||
PHOSTENT pHost = gethostbyname(szHostName);
|
||||
if(NULL == pHost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IN_ADDR Addr = {0,};
|
||||
int Count = 0;
|
||||
for(Count = 0;pHost->h_addr_list[Count]; ++Count)
|
||||
{
|
||||
memcpy(&Addr, pHost->h_addr_list[Count], sizeof(IN_ADDR));
|
||||
strncpy(Address_Out, inet_ntoa(Addr), nMaxBufferSize - 1);
|
||||
Address_Out[nMaxBufferSize - 1] = '\0';
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE>
|
||||
// 10.0.0.0 ~ 10.255.255.255
|
||||
// 172.16.0.0 ~ 172.31.255.255
|
||||
// 192.168.0.0 ~ 192.168.255.255
|
||||
if((unsigned char)10 == Addr.S_un.S_un_b.s_b1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if((unsigned char)172 == Addr.S_un.S_un_b.s_b1)
|
||||
{
|
||||
if(Addr.S_un.S_un_b.s_b2 >= (unsigned char)16 && Addr.S_un.S_un_b.s_b2 <= (unsigned char)31)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if((unsigned char)192 == Addr.S_un.S_un_b.s_b1)
|
||||
{
|
||||
if((unsigned char)168 == Addr.S_un.S_un_b.s_b2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(0 != Count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CTCPFactory::SetLinger(SOCKET hSocket, bool bOn, unsigned short usTimeOut)
|
||||
{
|
||||
linger socketLinger;
|
||||
|
||||
socketLinger.l_onoff = bOn ? 1 : 0;
|
||||
socketLinger.l_linger = usTimeOut;
|
||||
if(SOCKET_ERROR == setsockopt(hSocket, SOL_SOCKET, SO_LINGER,
|
||||
(char *)&socketLinger, sizeof(linger)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool CIPXFamilyFactory::SetAddr(LPSOCKADDR lpSA, char *szAddr, unsigned short usPort)
|
||||
{
|
||||
if(0 == szAddr) { return false; }
|
||||
|
||||
// get the offset for node number / network number separator
|
||||
LPSTR lpszNodeNum = strchr(szAddr, '.');
|
||||
if (0 == lpszNodeNum)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++lpszNodeNum;
|
||||
|
||||
LPSOCKADDR_IPX lpSA_ipx = reinterpret_cast<LPSOCKADDR_IPX>(lpSA);
|
||||
lpSA_ipx->sa_family = m_nSockFamily;
|
||||
|
||||
Math::Convert::AcToHe(szAddr,(char*)&lpSA_ipx->sa_netnum, 4);
|
||||
Math::Convert::AcToHe(lpszNodeNum,(char*)&lpSA_ipx->sa_nodenum, 6);
|
||||
lpSA_ipx->sa_socket = htons(usPort);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CIPXFamilyFactory::GetNetworkInfo(char *Address_Out, int nMaxBufferSize)
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#ifndef _SOCKET_FAMILY_H_
|
||||
#define _SOCKET_FAMILY_H_
|
||||
|
||||
class CSocketFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CSocketFactory() { }
|
||||
|
||||
SOCKET CreateConnectedSocket(const char* lpConnAddr, unsigned short usPort);
|
||||
SOCKET CreateBindedSocket(const char* lpBindAddr, unsigned short usPort);
|
||||
SOCKET CreateListenSocket(const char* lpListenAddr, unsigned short usPort, int nBackLog = MAX_BACKLOG);
|
||||
|
||||
virtual SOCKET CreateSocket();
|
||||
virtual bool GetNetworkInfo(char* Address_Out, int nMaxBufferSize) = 0;
|
||||
virtual bool SetAddr(LPSOCKADDR lpSA, const char* szAddr, unsigned short usPort) = 0;
|
||||
|
||||
inline int GetAddressLen() const { return m_nAddressLen; }
|
||||
|
||||
protected:
|
||||
|
||||
CSocketFactory(int nSocketFamily, int nSocketType,
|
||||
int nSocketProtocol, int nAddressLen);
|
||||
|
||||
enum { MAX_BACKLOG = 63 };
|
||||
|
||||
int m_nSockFamily;
|
||||
int m_nSockType;
|
||||
int m_nSockProtocol;
|
||||
int m_nAddressLen;
|
||||
};
|
||||
|
||||
|
||||
class CINETFamilyFactory : public CSocketFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual bool GetNetworkInfo(char* Address_Out, int nMaxBufferSize);
|
||||
virtual bool SetAddr(LPSOCKADDR lpSA, const char* szAddr, unsigned short usPort);
|
||||
|
||||
protected:
|
||||
|
||||
CINETFamilyFactory(int nSocketType, int nSocketProtocol);
|
||||
virtual ~CINETFamilyFactory() { }
|
||||
};
|
||||
|
||||
|
||||
class CTCPFactory : public CINETFamilyFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CTCPFactory();
|
||||
virtual ~CTCPFactory() { }
|
||||
static bool SetLinger(SOCKET hSocket, bool bOn, unsigned short usTimeOut);
|
||||
};
|
||||
|
||||
|
||||
class CUDPFactory : public CINETFamilyFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CUDPFactory();
|
||||
virtual ~CUDPFactory() { }
|
||||
};
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CIPXFamilyFactory : public CSocketFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual bool GetNetworkInfo(char* Address_Out, int nMaxBufferSize);
|
||||
virtual bool SetAddr(LPSOCKADDR lpSA, char* szAddr, unsigned short usPort);
|
||||
|
||||
protected:
|
||||
|
||||
CIPXFamilyFactory(int nSocketType, int nSocketProtocol);
|
||||
virtual ~CIPXFamilyFactory() { }
|
||||
};
|
||||
|
||||
|
||||
class CSPXFactory : public CIPXFamilyFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CSPXFactory();
|
||||
virtual ~CSPXFactory() { }
|
||||
};
|
||||
|
||||
|
||||
class CIPXFactory : public CIPXFamilyFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CIPXFactory();
|
||||
virtual ~CIPXFactory() { }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user