문자열(string, wsring)은 어떻게 보낼까?
char snedData[1000] = "가";
char snedData[1000] = u8"가";
WCHAR snedData[1000] = L"가";
TCHAR snedData[1000] = _T("가");
// 모두 메모리공간을 읽어보면 다르게 나오는데 무슨차일까?
// 서버와 클라를 어떻게 맞춰야할까?
- UNICODE & ENCODING
- 문자(Character)
- 문자 집합(Character Set) Vs 인코딩(Encoding)
- CP949 Vs UTF-8 Vs UTF-16
- MBCS(Multi Byte Character Set) Vs WBCS(Wide Byte Character Set)
문자(Character)
처음은 ASCII Code(문자집합)로 문자를 표현 (Ex> A == 0x41(65))
서로 다른 문자집합을 사용할 경우 문제가 발생함.
공통된 문자집합을 써보자 -> UNICODE 탄생
그런데 영어만 주로 쓰는 환경에서 UNICODE는 보통 2바이트를 쓰는데 이게 과연 효율적인가??
그래서 나온게 ENCODING! -> 만약 영어만 쓴다면 UTF-8로 ENCODING을 해줄께!
제일 앞 비트를 0으로 두면 UTF-8이라 가정한다(Ex> 0xxxxxxx)
만약 한글이라면 3바이트를 쓰고(1110xxxx 10xxxxxx 10xxxxxx) 이렇게 들어가 있으면 UTF-8 한글
그런데 한글은 꽤 널리 쓰이는데 3바이트나 쓰자고?? -> UTF-16의 탄생
UTF-16은 거의 Unicode를 그대로 쓴다
그럼 CP949는 뭔가? -> 문자 집합 2개를 동시에 사용함(KS-X-1003, KS-X-1001) MS(마소)에서 주로사용된다.
- MBCS(Multi Byte Character Set) : (char) 개별 문자를 다수의 바이트로 표현
- WBCS(Wide Byte Character Set) : (wchar) 유니코드 기반의 character set(UTF-16)
char snedData[1000] = "가"; // CP949 (한글2바이트, 로마자1바이트)
char snedData[1000] = u8"가"; // UTF8 (Unicode)
WCHAR snedData[1000] = L"가"; // UTF16 (Unicode)
TCHAR snedData[1000] = _T("가");
#include "pch.h"
#include "ThreadManager.h"
#include "Service.h"
#include "Session.h"
#include "GameSession.h"
#include "GameSessionManager.h"
#include "BufferWriter.h"
#include "ServerPacketHandler.h"
#include <tchar.h>
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();
}
});
}
WCHAR sendData3[1000] = L"가"; // UTF16 = Unicode (한글/로마 2바이트)
while (true)
{
vector<BuffData> buffs{ BuffData {100, 1.5f}, BuffData{200, 2.3f}, BuffData {300, 0.7f } };
SendBufferRef sendBuffer = ServerPacketHandler::Make_S_TEST(1001, 100, 10, buffs, L"안녕하세요");
GSessionManager.Broadcast(sendBuffer);
this_thread::sleep_for(250ms);
}
GThreadManager->Join();
}
class ServerPacketHandler
{
public:
static void HandlePacket(BYTE* buffer, int32 len);
static SendBufferRef Make_S_TEST(uint64 id, uint32 hp, uint16 attack, vector<BuffData> buffs, wstring name);
// wstring name을 보냄을 주목
};
SendBufferRef ServerPacketHandler::Make_S_TEST(uint64 id, uint32 hp, uint16 attack, vector<BuffData> buffs, wstring name)
{
SendBufferRef sendBuffer = GSendBufferManager->Open(4096);
BufferWriter bw(sendBuffer->Buffer(), sendBuffer->AllocSize());
PacketHeader* header = bw.Reserve<PacketHeader>();
// id(uint64), 체력(uint32), 공격력(uint16)
bw << id << hp << attack;
// 가변 데이터
bw << (uint16)buffs.size();
for (BuffData& buff : buffs)
{
bw << buff.buffId << buff.remainTime;
}
bw << (uint16)name.size();
bw.Write((void*)name.data(), name.size() * sizeof(WCHAR));
header->size = bw.WriteSize();
header->id = S_TEST; // 1 : Test Msg
sendBuffer->Close(bw.WriteSize());
return sendBuffer;
}
void ClientPacketHandler::Handle_S_TEST(BYTE* buffer, int32 len)
{
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;
vector<BuffData> buffs;
uint16 buffCount;
br >> buffCount;
buffs.resize(buffCount);
for (int32 i = 0; i < buffCount; i++)
{
br >> buffs[i].buffId >> buffs[i].remainTime;
}
cout << "BufCount : " << buffCount << endl;
for (int32 i = 0; i < buffCount; i++)
{
cout << "BufInfo : " << buffs[i].buffId << " " << buffs[i].remainTime << endl;
}
wstring name;
uint16 nameLen;
br >> nameLen;
name.resize(nameLen);
br.Read((void*)name.data(), nameLen * sizeof(WCHAR));
wcout.imbue(std::locale("kor"));
wcout << name << endl;
}