네트워크 프로그래밍 2주차

Hyun·2024년 10월 5일
0

2. 소켓 프로그래밍

2.1. 윈도우의 오류 처리

  1. 오류를 처리할 필요가 없는 경우: 리턴값이 없거나 호출 시 항상 성공하는 일부 소켓 함수
  2. 리턴값만으로 오류를 처리하는 경우 : WSAStartup() 함수
  3. 리턴값만으로 오류 발생을 확인하고, 구체적인 내용은 오류 코드로 확인 (대부분)

리턴값 + 오류코드 사용 예시 : 네트워크 작업 중 오류가 발생하면 가장 최근에 발생한 오류의 정수형 오류 코드를 반환한다.

#include <winsock2.h> // WSAGetLastError() 함수가 선언되어 있다.
...
if (소켓함수 (...) == 실패) {
	printf(WSAGetLastError()에 해당하는 오류 메세지)
}

FormatMessage() 함수: 오류 코드 > 오류 메세지
WORD(16바이트), Double-WORD(32비트)

#include <windows.h>
DWORD FormatMessage(
	DWORD dwFlags, // 메세지를 가져오는 Format 설정을 위해 사용될 옵션
    LPCVOID lpSource, // 오류 메세지를 어디서 가져올지 지정하는 파라미터, default: NULL
    DWORD dwMessageId, // 오류 코드
    DWORD dwLanguageId, // 언어
    LPTSTR lpBuffer, // 오류 문자열 시작 주소
    DWORD nSize, // 버퍼의 크기, default: 0
    va_list *Arguments // 매개변수들, default: NULL
};

err_quit() 함수 정의: 에러 메시지를 메시지 박스 형태로 출력 + 프로세스 종료

void err_quit(const char *msg)
{
 LPVOID lpMsgBuf;
 FormatMessage(
 	FORMAT_MESSAGE_ALLOCATE_BUFFER //오류 메세지를 위한 공간 자동 할당
    | FORMAT_MESSAGE_FROM_SYSTEM, // 운영체제로부터 오류 메세지 가져옴
    NULL, WSAGetLastError(), // 윈속 관련 함수에서 마지막으로 발생한 오류 코드
    MAKELANGID(LANG_NEUTRAL, SUBLANG DEFAULT), // 오류 메세지의 언어 설정
    (char*)&IpMsgBuf, 0, NULL); // 오류 메세지
 MessageBoxA(NULL, (const char*)IpMsgBuf, msg, MB_ICONERROR);
 LocalFree(IpMsgBuf);
 exit(1);

err_quit() 사용 예시

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

err_display() 함수 정의: 최근 오류에 대한 에러 메세지만 출력

void err_display(const char *msg)
{
 LPVOID lpMsgBuf;
 FormatMessageA (
 	FORMATE_MESSAGE_ALLOCAT_BUFFER
    | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL, WSAGetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (char*)&lpMsgBuf, 0, NULL);
    printf("[%s]%s\n", msg, (char*)lpMsgBuf);
    LocalFree(lpMsgBuf);
}
// err_quit와 다르게 단순히 printf로 로그만 작성, 프로그램을 종료하지 않음

err_display() 함수 정의: 주어진 errcode 기준으로 에러 메시지 출력

void err_display(int errcode)
{
 LPVOID lpMsgBuf;
 FormatMessageA (
 	FORMATE_MESSAGE_ALLOCAT_BUFFER
    | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL, errcode,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (char*)&lpMsgBuf, 0, NULL);
    printf("[오류]%s\n", msg, (char*)lpMsgBuf);
    LocalFree(lpMsgBuf);
}

2.2. 소켓 초기화와 종료

WSAStartUp()
1. 윈속 동적 연결 라이브러리를 초기화
2. 윈속 구현이 애플리케이션 요구사항을 충족하는지 확인

WSACleanup(): 더 이상 윈속을 사용하지 않을 때 이를 해제

2.2.1. 윈속 초기화

int WSAStartup(
	WORD wVersionRequested,
    LPWSADATA lp WSAData
);

2.2.2. 윈속 종료

int WSACleanup(void);

2.3. 소켓 생성과 닫기

socket()
1. 사용자가 요청한 프로토콜로 통신할 수 있도록 리소스 할당
2. 소켓 핸들값 반환

closesocket(): 소켓을 닫고 리소스를 반환

2.3.1. 소켓 생성

#include <winsock2.h>
SOCKET socket (
	 int af, //주소 체계 
     int type, // 소켓 타입
     int protocol // 프로토콜
    );

사용자가 요청한 프로콜을 사용해 통신할 수 있도록 내부적으로 리소스 할당,
이에 접근할 수 있는 일종의 핸들값 (소켓 디스크립터)를 리턴

  1. 주소 체계 (프로토콜 체계, Protocol Family PF)
  2. 소켓 타입

  1. 프로토콜
    : 주소 체계와 소켓 타입이 같더라도 해당 프로토콜이 두 개 이상 존재할 경우 프로토콜을 명시적으로 지정

2.3.2. 소켓 닫기

#include <winsock2.h>
int closesocket(
	SOCKETs
    );

소켓을 닫고 관련 리소스를 운영체제에 반환.

0개의 댓글

관련 채용 정보