출처: TCP/IP 윈도우 소켓 프로그래밍(https://product.kyobobook.co.kr/detail/S000001636201)
네트워크 프로그램은 여러 원인 때문에 오류가 발생할 수 있으며, 발생 확률도 비교적 높다. 따라서 함수 호출 시 오류를 체크하고 사용자에게 구체적인 오류 내용을 알려주는 것이 매우 중요하다.
윈도우 소켓 함수는 오류 처리 방법에 따라 다음과 같이 세 가지 유형으로 나눌 수 있다.
- 오류를 처리할 필요가 없는 경우: 리턴 값이 없거나 호출 시 항상 성공하는 일부 소켓 함수가 여기에 해당된다.
- 리턴 값만으로 오류를 처리하는 경우:
WSAStartup()
함수 - 리턴 값으로 오류 발생을 확인하고, 구체적인 내용은 오류 코드로 확인하는 경우: 대부분의 소켓 함수가 여기에 해당된다.
여기에 1번과 2번 유형은 해당하는 특별한 경우에 따로 확인하면 되는 부분이고, 3번이 대다수의 소켓 함수에 적용되기 때문에 3번을 알아볼 것이다.
소켓 함수 호출 결과 오류가 발생했다면 WSAGetLastError()
함수를 사용해 오류 코드를 얻을 수 있으며, 오류 코드를 사용자가 알아보기 쉽도록 문자열로 변환하기 위해서는 FormatMessage()
함수를 사용하면 된다. 다음은 특정 소켓 함수를 호출하고 오류가 발생했을 때 어떤 방식으로 처리하는지에 대한 예시이다.
// listen()에서 오류 발생
retval = listen(listen_sock, SOMAXCONN);
if(retval == SOCKET_ERROR) err_quit("listen()");
listen
이라는 소켓 함수를 호출했는데, 리턴 값이 오류를 나타낸다면(여기에서는 SOCKET_ERROR
) 구체적인 오류 내용을 확인하기 위해 err_quit
함수를 호출하고 있다.
err_quit
함수는 소켓 함수 호출 과정에서 발생한 오류의 내용을 출력하기 위한 함수이다. 함수 내부에서는 FormatMessage
함수를 이용하여 오류 코드에 대응하는 오류 메시지를 얻어 메시지 박스로 출력해준다.
// 소켓 함수 오류 출력 후 종료
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, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(1);
}
FormatMessage
함수의 각 매개 변수는 다음과 같은 용도로 사용된다.
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage
DWORD FormatMessage(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPSTR lpBuffer,
DWORD nSize,
va_list *Args
)
dwFlags
: 오류 메시지 출력을 위한 플래그를 설정한다. 여기에서 사용된 플래그는 다음과 같은 역할을 한다.FORMAT_MESSAGE_ALLOCATE_BUFFER
: 오류 메시지를 저장할 공간을FormatMessage
함수에서 알아서 할당한다.FORMAT_MESSAGE_FROM_SYSTEM
: 운영체제로부터 오류 메시지를 가져온다는 의미이다.
lpSource
: 메시지 정의의 위치를 나타낸다.dwFlags
의 파라미터에 따라 값이 세팅되는데, 위에서 설정한 플래그를 사용할 경우에는NULL
을 입력해주면 된다.(특정 플래그가 아니라면 무시된다. 공식 문서 참조)dwMessageId
: 오류 코드를 나타낸다.WSAGetLastError
함수의 리턴 값을 여기에 넣으면 된다.WSAGetLastError
는 단순히 가장 최근에 발생한 윈도우 소켓 함수의 오류 코드를 리턴한다. 따라서 윈도우 소켓 함수를 호출하고 오류가 발생했다면 즉시 오류 메시지를 확인할 필요가 있다. 그렇지 않다면 언제 어디서 발생한 오류인지 추적할 수 없게 된다.
dwLanguageId
: 오류 메시지를 표시할 언어를 나타낸다.MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
를 사용하면 사용자가 제어판에서 설정한 기본 언어로 오류 메시지를 얻게 된다.
lpBuffer
: 오류 메시지가 담기는 버퍼이다. 오류 메시지의 시작 주소가 저장된다.- 저장에 필요한 메모리 공간은
dwFlags
에서FormatMessage
함수에 일임했기 때문에 오류 메시지 사용을 마쳤으면LocalFree
함수를 사용해 메모리를 반환해야 한다.
- 저장에 필요한 메모리 공간은
nSize
:FORMAT_MESSAGE_ALLOCATE_BUFFER
플래그가 설정되었기 때문에TCHAR
문자열이 가질 수 있는 가장 작은 숫자인 0을 입력한다.FORMAT_MESSAGE_ALLOCATE_BUFFER
플래그가 설정되지 않고 직접lpBuffer
를 지정했다면, 지정한 크기를 입력해준다. 크기는 64kb를 넘을 수 없다.
Args
: 형식 지정 메시지에 삽입 값으로 사용되는 값들의 배열이다. 형식 지정 메시지에서%1
을 사용했으면 이는Args
배열의 첫 번째 값을 나타낸다.
'네트워크 > 윈도우 소켓 프로그래밍' 카테고리의 다른 글
TCP 클라이언트 함수 (0) | 2024.04.05 |
---|---|
TCP 서버 함수 (0) | 2024.04.05 |
소켓 주소 구조체 다루기 (0) | 2024.04.04 |
소켓의 생성과 닫기 (0) | 2024.04.01 |
윈도우 소켓 애플리케이션 초기화 및 종료 (0) | 2024.04.01 |