(C++ : IOCP-46) UniCode

Posted by : at

Category : Cpp   iocp


문자열(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;
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links