Windows의 MultiByteToWideChar/WideCharToMultiByte 용법과 wchar_t, CP_ACP의 의미

MultiByteToWideChar/WideCharToMultiByte 함수는 여기저기서 많이 쓰던 함수이다. MSDN을 보고 사용 코드를 짜보기도 하고 (이 블로그 옛날 글에도 있다.) 나중에는 귀찮으니 인터넷에 있는거 후려다 쓰기도 했다. 용법은 인터넷에 많이 있으니 패스하고 해당 함수를 사용하면서 언제나 헷갈리는 점이 있는데, 파라메터중 코드페이지 이다.

결론 부터 말하면 두 함수의 첫번째 인자인 코드페이지의 의미가 서로 다르다.
MultiByteToWideChar는 변환하려는 멀티바이트의 코드페이지를 의미한다. 즉 코드페이지에 해당하는 멀티바이트가 들어가서 와이트캐릭터로 나온다.
WideCharToMultiByte는 결과로 나오는 멀티바이트의 코드페이지를 의미한다. 즉 와이드캐릭터가 들어가서 코드페이지에 해당하는 멀티바이트로 나온다.

와이드캐릭터의 입력이나 출력에 코드페이지나 인코딩 형태를 입력하지 않는것을 보면 Windows의 와이드캐릭터는 코드 페이지가 존재하지 않는다는 의미이다. 2바이트 캐릭터라고 해도 인코딩 방식은 여러가지 일텐데 왜 코드페이지가 없는가? C++에서 wchar_t는 2바이트 캐릭터타입이라는 의미이지 특정 인코딩이나 코드페이지를 의미하는것이 아니다.

Windows의 관련 인터넷을 뒤져보니 UTF16 고정인듯 한다. (BE, LE중 뭔지도 좀 구분해서 써주지)
1. https://docs.microsoft.com/en-us/windows/win32/learnwin32/working-with-strings
2. https://docs.microsoft.com/ko-kr/cpp/standard-library/filesystem?view=vs-2019

그리고 위 함수의 인자인 코드페이지 가장 많이 사용하는 값인 CP_ACP.
일반적으로 asni 라고도 하는데, 실제로는 실행되고 있는 윈도우(OS)의 디폴트 코드페이지를 의미한다. 즉 국가별로 CP_ACP는 다른 코드페이지 이다.

그래서 중국 윈도우에서 실행된 클라이언트에서 입력한 멀티바이트 문자열을 한국(OS) 서버에서 MultiByteToWideChar 함수에 CP_ACP로 지정해서 변환하면 깨진다.

오랜 기간 C++을 했지만 문자열 인코딩에 대해서 생각이란걸 해보게 된건 최근이다. 그 전에는 이렇게 해보고 ‘아 안되네?’ 다른 값 넣어보고 ‘음 되네’. OS가 바뀌면 되던게 안되기도 하고 그랬다.

약간 다른 문제이지만… 요즘엔 회사에서 Perforce를 쓰는데 소스 코드든 설정 파일이든 그냥 넣은대로 나왔으면 좋겠는데, 내려받을때 다시 인코딩을 변환해서 골때린다.

Window Network Programming IO모델

1 OS별 사용 가능한 소켓 I/O 모델











































































OS Blocking Non-blocking Select WSAAsync Select WSAEvent Select Overlapped Completion Port
WindowsCE O O X X X X
Window 95(Winsock 1) O O O X X X
Window 95(Winsock 2) O O O O O X
Window 98 O O O O O X
Window Me O O O O O O
Window NT O O O O O O
Window 2000 O O O O O O
Window XP O O O O O O

2 넌블럭킹 소켓에서 WSAWOULDBLOCK 에러의 의미





















함수 WSAWOULDBLOCK 에러의 의미
WSAAccept, accept 아직 연결 요청을 받지 못함
closesocket 대부분 setsockopt함수의 SO_LINGER 옵션을 설정하고 타임아웃을 설정한 경우
WSAConnect, connect 연결을 시도함
WSARecvm, recv, WSARecvFrom, recvfrom 데이타를 아직 받지 못함. 다시한번 호출하여 검사할것
WSASend, send,
WSASendTo, sendto
데이타를 전송할 버퍼 공간이 없음. 나중에 다시 시도할것