728x90
반응형
IOCP Core
이제 IOCP모델을 서버코어에 넘겨주어야 하기 떄문에 세분화 하여 정리할 필요가 있다.
IOCP의 핵심 요약
- CreateIocompletionport를 사용하여 (초기화된)CP큐를 생성한다.
- CP에 연결할 객체(Object)를 생성한다.
- CreateIocompletionport를 이용하여 생성한 객체를 CP에 등록한다(관찰대상 등록)
- WSARecv를 사용하여 WorkerThread에게 전송을 맡긴다(이때 WorkerThread에서 마지막에 WSARecv를 호출해야된다)
IOCP Core
IOCP모델의 CP큐를 담당하는 클래스이다.
//IOCPCore.h
class IocpObject : public enable_shared_from_this<IocpObject>
{
public:
virtual HANDLE GetHandle()abstract;
virtual void Dispatch(class IocpEvent* iocpEvent, int32 numOfBytes = 0) abstract;
};
//CP에 연결할 관찰대상을 상속시키기 위한 클래스
class IocpCore //CP큐
{
IocpCore();
~IocpCore();
HANDLE GetHandle() { return _iocphandle; }
bool Register(shared_ptr<locpObject> iocpObject);
//Session이나 Object를 CP큐에 등록<-CreateIoCompletionPort
bool Dispatch(uint32 timeoutMs=INFINITE);
//워커쓰레드들이 일감을 꺼내가는 함수<-GetQueueCompletionStatus
private:
HANDLE _iocphandle;
}
//IOCPCore.cpp
IocpCore::IocpCore()
{
_iocphandle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
//(초기화된)CP큐를 생성
assert(_iocphandle!= INVALID_HANDLE_VALUE);
}
IocpCore::~IocpCore()
{
::CloseHandle(_iocphandle);
}
bool IocpCore::Register(shared_ptr<IocpObject> iocpObject)
{
return ::CreateIoCompletionPort(iocpObject->GetHandle(),_iocphandle,0,0);;
//오브젝트를 CP에 등록(관찰대상으로 등록)
}
bool IocpCore::Dispatch(uint32 timeoutMs)
{
DWORD numOfbyte = 0;
ULONG_PTR key = 0;
shared_ptr<IocpObject> iocpobj = nullptr;//Cp큐에 등록할 오브젝트
IocpEvent* iocpevnt = nullptr;//특정이벤트 구분을 위한 IocpEvent객체
if (::GetQueuedCompletionStatus(_iocphandle, OUT & numOfbyte, OUT static_cast<PULONG_PTR>(&key), OUT reinterpret_cast<LPOVERLAPPED*>(&iocpevnt), timeoutMs))
{
iocpobj = iocpevnt->owner;//RefCount를 위해서
iocpobj->Dispatch(iocpevnt, numOfbyte);
}
else
{
int32 err = ::WSAGetLastError();
switch (err)
{
case WAIT_TIMEOUT:
return false;
default:
iocpobj = iocpevnt->owner;//RefCount를 위해서
iocpobj->Dispatch(iocpevnt,numOfbyte);
break;
}
}
return false;
}
IOCP Event
IOCP모델은 Overlapped모델을 확장한 모델이다. Overlapped모델에서는 특정한 이벤트들을 구분하고 처리해주는 역할을 했었는데, 이러한 부분들을 처리해줄 클래스가 바로 IOCP Event부분이다.
//IOCPEvent.h
class Session;
enum class EventType :uint8
{
Connect,
Disconnect,
Accept,
Recv,
Send,
};
class IocpEvent
{
public:
OVERLAPPED overlapped = {};
IocpEvent(EventType type);
void Init();
shared_ptr<Session> owner=nullptr;
EventType _type;
shared_ptr<Session> session = nullptr;
};
//IOCPEvent.cpp
IocpEvent::IocpEvent(EventType type):_type(type)
{
Init();
}
void IocpEvent::Init()
{
overlapped.hEvent = 0;
overlapped.Internal = 0;
overlapped.InternalHigh = 0;
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
}
NetAddress
번잡하게 관리될수 있는 IP주소를 맵핑하고 관리하는 클래스이다.
//NetAddress.h
class NetAddress
{
public:
NetAddress()=default;
NetAddress(SOCKADDR_IN sockAddr);
NetAddress(std::wstring ip,uint16 port);
SOCKADDR_IN& GetSockAddr() { return _sockAddr; }
std::wstring GetIpAddress();
uint16 Getport() { return ::ntohs(_sockAddr.sin_port); }
public:
static IN_ADDR Ip2Address(const WCHAR* ip);
private:
SOCKADDR_IN _sockAddr = {};
};
//NetAddress.cpp
NetAddress::NetAddress(SOCKADDR_IN sockAddr):_sockAddr(sockAddr)
{
}
NetAddress::NetAddress(wstring ip, uint16 port)
{
::memset(&_sockAddr,0,sizeof(_sockAddr));
_sockAddr.sin_family = AF_INET;
_sockAddr.sin_port = ::htons(port);
_sockAddr.sin_addr = Ip2Address(ip.c_str());
}
std::wstring NetAddress::GetIpAddress()
{
WCHAR buffer[100];
::InetNtopW(AF_INET, &_sockAddr.sin_addr, buffer, len32(buffer));
return wstring(buffer);
}
IN_ADDR NetAddress::Ip2Address(const WCHAR* ip)
{
IN_ADDR address;
::InetPtonW(AF_INET, ip, &address);
return address;
}
4.Listener:관찰대상..?
728x90
반응형
'게임서버' 카테고리의 다른 글
게임서버) 8. Select모델 (0) | 2023.01.13 |
---|---|
게임서버) 7. 논블로킹 소켓 (0) | 2023.01.12 |
게임서버) 6. 소켓프로그래밍 (0) | 2023.01.11 |
게임서버) 3.멀티쓰레드 공유자원 (0) | 2023.01.06 |
게임서버) 2. 멀티쓰레드 (0) | 2023.01.06 |
댓글