게임서버 공부_winsock_error_handler

오류 처리

네트워크 프로그래밍에서는 오류가 자주 발생한다. 그러므로 오류 발생시 정확한 정보를 전달받을 수 있게 오류처리를 할 필요가 있다. 오류 처리를 하는 방법은 아래와 같은 세가지 유형이다.

  1. 오류 처리할 필요 없는 경우 : 리턴 값이 없거나 항상 성공하는 소켓 함수
  2. 리턴 값만으로 오류를 알수 있는 함수 : WSAStartup() 등
  3. 리턴 값으로는 오류 여부만 파악하고, 구체적 내용은 오류코드로 확인해야 하는 경우 : 대부분의 소켓 함수.

3번의 경우 에러코드를 바탕으로 어떠한 문제때문에 에러가 발생했는지 확인할 필요가 있다. 윈도우에서는 int WSAGetLastError(void)를 통해 가장 최근에 발생한 에러의 에러코드를 얻을수 있다. 이를 FormatMessage함수를 사용하여 오류코드를 해석할수 있다.

DWORD FormatMessage(
  [in]           DWORD   dwFlags,
  [in, optional] LPCVOID lpSource,
  [in]           DWORD   dwMessageId,
  [in]           DWORD   dwLanguageId,
  [out]          LPTSTR  lpBuffer,
  [in]           DWORD   nSize,
  [in, optional] va_list *Arguments
);

코드

void err_quit(char *msg)
{
	LPVOID lpMsgBuf;
	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, WSAGetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR)&lpMsgBuf, 0, NULL);
	MessageBox(NULL, (LPCUTSTR)lpMsgBuf, msg, MB_ICONERROR);
	LocalFree(lpMsgBuf);
	exit(1);
}

...
if (socket(...) == INVALID_SOCKET) err_quit("socket()");
...

void err_display(char* msg)
{
	LPVOID lpMsgBuf;
	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, WSAGetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR)&lpMsgBuf, 0, NULL);
	printf("[%s] %s", msg, (LPCUTSTR)lpMsgBuf);
	LocalFree(lpMsgBuf);
}

...
if (socket(...) == INVALID_SOCKET) err_display("socket()");
...