버퍼에 데이터 쓰고 읽는데 도움주는 클래스를 만들어 보자.
BufferReader.h, BufferReader.cpp
#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);
template<typename T>
BufferReader& operator>>(OUT T& dest);
private:
BYTE* _buffer = nullptr;
uint32 _size = 0;
uint32 _pos = 0;
};
template<typename T>
BufferReader& BufferReader::operator>>(OUT T& dest)
{
dest = *reinterpret_cast<T*>(&_buffer[_pos]);
_pos += sizeof(T);
return *this;
}
#include "pch.h"
#include "BufferReader.h"
/*--------------------
BufferReader
--------------------*/
BufferReader::BufferReader()
{
}
BufferReader::BufferReader(BYTE* buffer, uint32 size, uint32 pos /*=0*/)
:_buffer(buffer), _size(size), _pos(pos)
{
}
BufferReader::~BufferReader()
{
}
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;
}
BufferWriter.h, BufferWriter.cpp
#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);
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;
}
#include "pch.h"
#include "BufferWriter.h"
/*--------------------
BufferWriter
--------------------*/
BufferWriter::BufferWriter()
{
}
BufferWriter::BufferWriter(BYTE* buffer, uint32 size, uint32 pos)
:_buffer(buffer), _size(size), _pos(pos)
{
}
BufferWriter::~BufferWriter()
{
}
bool BufferWriter::Write(void* src, uint32 len)
{
if (FreeSize() < len)
return false;
::memcpy(&_buffer[_pos], src, len);
_pos += len;
return true;
}
BufferWriter는 아래처럼 사용
GameServer.cpp
...
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);
}
...
BufferReader는 아래처럼 사용
DummyClient.cpp
...
virtual int32 OnRecvPacket(BYTE* buffer, int32 len) override
{
BufferReader br(buffer, len);
PacketHeader header;
br >> header;
uint64 id;
uint32 hp;
uint16 attack;
br >> id >> hp >> attack;
cout << "ID: " << id << " HP : " << hp << " ATT : " << attack << endl;
char recvBuffer[4096];
br.Read(recvBuffer, header.size - sizeof(PacketHeader) - 8 - 4 - 2);
cout << recvBuffer << endl;
return len;
}
...
1. BufferReader operator >> 이 하는 역할은?
- 데이터를 읽고 position을 읽은 만큼 이동시킴.
2. Peek 의 역할은?
- 데이터를 파싱할 수 있는지 확인함.
3. BufferReader 사용법과 설명, BufferWriter 사용법과 설명?
- BufferReader : Iocp Recv 이벤트 받음> ProcessRecv > OnRecv > OnRecvPacket 에서 write한 순서대로 읽음 마지막 len 계산은 가변길이 정보 읽는 방법 보여준 것.
- BufferWriter : SendBufferRef 생성 > BufferWriter 생성 > '<<' operator로 write > 'Hello World' 가변길이 데이터 보내기
Unicode (0) | 2023.05.07 |
---|---|
PacketHandler (0) | 2023.05.06 |
Packet Session (0) | 2023.04.16 |
SendBuffer Pooling (0) | 2023.04.05 |
SendBuffer (0) | 2021.12.21 |
댓글 영역