윈도우 소켓 깔끔하게 작성해보기

2025. 3. 11. 23:45·C++/네트워크
#pragma comment(lib,"ws2_32.lib")

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <iostream>

class WSAInitializer {
public:
    WSAInitializer() {
        int result = WSAStartup(MAKEWORD(2, 2), &wsaData_);
        if (result != 0) {
            throw std::runtime_error("WSAStartup failed");
        }
    }

    ~WSAInitializer() {
        WSACleanup();
    }

    WSADATA& GetWSAData() {
        return wsaData_;
    }

private:
    WSADATA wsaData_;
};

int main() {
    try {
        // 초기화
        WSAInitializer wsaInit;

        // 주소정하기
        ADDRINFO addressFilter{
            .ai_flags = AI_PASSIVE,
            .ai_family = AF_INET,
            .ai_socktype = SOCK_STREAM,
        };
        ADDRINFO *address;
        ::getaddrinfo(NULL, "3333", &addressFilter, OUT &address);

        //SOCKET 생성
        SOCKET serverSocket = ::socket(address->ai_family, 
            address->ai_socktype, 
            address->ai_protocol);

        // bind
        ::bind(serverSocket, address->ai_addr, address->ai_addrlen);

    }
    catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

WSA함수

이전과 다르게 WSA를 C++의 RAII(RAII: Resource Acquisition Is Initialization) 패턴을 활용해서

생성하고 소멸시점에서 WSA의 함수들을 사용하게 만들어서 코드를 작성했다.

class WSAInitializer {
public:
    WSAInitializer() {
        int result = WSAStartup(MAKEWORD(2, 2), &wsaData_);
        if (result != 0) {
            throw std::runtime_error("WSAStartup failed");
        }
    }

    ~WSAInitializer() {
        WSACleanup();
    }

    WSADATA& GetWSAData() {
        return wsaData_;
    }

private:
    WSADATA wsaData_;
};

ADDRINFO

ADDRINFO가 새롭게 배운 객체인데 getAddrinfo를 통해서 특정주소에 대한 주소정보를 가지고 올수 있다. 

하지만 getaddrinfo에 특정주소 예) "192.168.1.0", "www.google.com" 이 아닌NULL을 사용하면 호스트의 주소에 대한 정보를 마지막인자를 통해서 받을 수 있다.

 ADDRINFO addressFilter{
     .ai_flags = AI_PASSIVE,
     .ai_family = AF_INET,
     .ai_socktype = SOCK_STREAM,
 };
 ADDRINFO *address;
 ::getaddrinfo(NULL, "3333", &addressFilter, OUT &address);

 //SOCKET 생성
 SOCKET serverSocket = ::socket(address->ai_family, 
     address->ai_socktype, 
     address->ai_protocol);

 

이전에 작성했던 코드 Socket생성

sockfd = socket(AF_INET, SOCK_STREAM, 0);

이전에 코드는 직접 소켓의 주소를 넣어줬다면 ADDRINFO를 통해서 좀더 안전하게 socket을 생성할수 있다.

'C++ > 네트워크' 카테고리의 다른 글

다시써보는 에코서버2 window 버전  (1) 2024.06.02
다시써보는 에코클라이언트 Linux 버전  (0) 2024.06.01
다시 써보는 에코서버 window 버전  (0) 2024.06.01
'C++/네트워크' 카테고리의 다른 글
  • 다시써보는 에코서버2 window 버전
  • 다시써보는 에코클라이언트 Linux 버전
  • 다시 써보는 에코서버 window 버전
교쟁이
교쟁이
  • 교쟁이
    Just Do it!!!
    교쟁이
  • 전체
    오늘
    어제
    • 분류 전체보기 (29)
      • C++ (2)
        • 자료구조 (0)
        • CMake (0)
        • 기초 (2)
        • 네트워크 (4)
      • 항해99 (15)
        • WIL (4)
      • Back-end (3)
        • DATABASE (3)
      • 글쓰기 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    테스트
    신입개발자
    파이널 프로젝트
    항해99 #nodejs
    Jest
    자바스크립트
    스타트업
    비전공자
    동생
    database
    항해 플러스
    programming
    개발자
    항해 플러스 #테라폼
    코드스테이츠
    네카라쿠배
    socket
    TCP/IP
    항해 플러스 # CI/CD #Terraform
    항해99
    sql #database
    부트캠프
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
교쟁이
윈도우 소켓 깔끔하게 작성해보기
상단으로

티스토리툴바