역시 쉬워서 별도로 정리하지 않음.
패킷 Read/Write Helper정도라 생각하면 된다
#pragma once
/*----------------
BufferWriter
-----------------*/
class BufferWriter
{
public:
BufferWriter();
BufferWriter(BYTE* buffer, uint32 size, uint32 pos = 0);
~BufferWriter();
BYTE* Buffer() { return _buffer; }
uint32 Size() { return _size; }
uint32 WriteSize() { return _pos; }
uint32 FreeSize() { return _size - _pos; }
template<typename T>
bool Write(T* src) { return Write(src, sizeof(T)); }
bool Write(void* src, uint32 len);
/*
bool BufferWriter::Write(void* src, uint32 len)
{
if (FreeSize() < len)
return false;
::memcpy(&_buffer[_pos], src, len);
_pos += len;
return true;
}
*/
template<typename T>
T* Reserve();
template<typename T>
BufferWriter& operator<<(const T& src);
template<typename T>
BufferWriter& operator<<(T&& src);
private:
BYTE* _buffer = nullptr;
uint32 _size = 0;
uint32 _pos = 0;
};
template<typename T>
T* BufferWriter::Reserve()
{
if (FreeSize() < sizeof(T))
return nullptr;
T* ret = reinterpret_cast<T*>(&_buffer[_pos]);
_pos += sizeof(T);
return ret;
}
template<typename T>
BufferWriter& BufferWriter::operator<<(const T& src)
{
*reinterpret_cast<T*>(&_buffer[_pos]) = src;
_pos += sizeof(T);
return *this;
}
template<typename T>
BufferWriter& BufferWriter::operator<<(T&& src)
{
*reinterpret_cast<T*>(&_buffer[_pos]) = std::move(src);
_pos += sizeof(T);
return *this;
}
#pragma once
/*----------------
BufferReader
-----------------*/
class BufferReader
{
public:
BufferReader();
BufferReader(BYTE* buffer, uint32 size, uint32 pos = 0);
~BufferReader();
BYTE* Buffer() { return _buffer; }
uint32 Size() { return _size; }
uint32 ReadSize() { return _pos; }
uint32 FreeSize() { return _size - _pos; }
template<typename T>
bool Peek(T* dest) { return Peek(dest, sizeof(T)); }
bool Peek(void* dest, uint32 len);
template<typename T>
bool Read(T* dest) { return Read(dest, sizeof(T)); }
bool Read(void* dest, uint32 len);
/*
bool BufferReader::Peek(void* dest, uint32 len)
{
if (FreeSize() < len)
return false;
::memcpy(dest, &_buffer[_pos], len);
return true;
}
bool BufferReader::Read(void* dest, uint32 len)
{
if (Peek(dest, len) == false)
return false;
_pos += len;
return true;
}
*/
template<typename T>
BufferReader& operator>>(OUT T& dest);
private:
BYTE* _buffer = nullptr;
uint32 _size = 0;
uint32 _pos = 0;
};
template<typename T>
inline BufferReader& BufferReader::operator>>(OUT T& dest)
{
dest = *reinterpret_cast<T*>(&_buffer[_pos]);
_pos += sizeof(T);
return *this;
}
int main()
{
ServerServiceRef service = MakeShared<ServerService>(
NetAddress(L"127.0.0.1", 7777),
MakeShared<IocpCore>(),
MakeShared<GameSession>, // TODO : SessionManager 등
100);
ASSERT_CRASH(service->Start());
for (int32 i = 0; i < 5; i++)
{
GThreadManager->Launch([=]()
{
while (true)
{
service->GetIocpCore()->Dispatch();
}
});
}
char sendData[1000] = "Hello World";
while (true)
{
SendBufferRef sendBuffer = GSendBufferManager->Open(4096);
BufferWriter bw(sendBuffer->Buffer(), 4096);
PacketHeader* header = bw.Reserve<PacketHeader>();
// id(uint64), 체력(uint32), 공격력(uint16)
bw << (uint64)1001 << (uint32)100 << (uint16)10;
bw.Write(sendData, sizeof(sendData));
header->size = bw.WriteSize();
header->id = 1; // 1 : Test Msg
sendBuffer->Close(bw.WriteSize());
GSessionManager.Broadcast(sendBuffer);
this_thread::sleep_for(250ms);
}
GThreadManager->Join();
}
int main()
{
this_thread::sleep_for(1s);
ClientServiceRef service = MakeShared<ClientService>(
NetAddress(L"127.0.0.1", 7777),
MakeShared<IocpCore>(),
MakeShared<ServerSession>, // TODO : SessionManager 등
1000);
ASSERT_CRASH(service->Start());
for (int32 i = 0; i < 2; i++)
{
GThreadManager->Launch([=]()
{
while (true)
{
service->GetIocpCore()->Dispatch();
}
});
}
GThreadManager->Join();
}