DevelopmentπŸ‘©πŸ»‍🦳/Communication

μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°μ˜ μ‹œμž‘: μ£Όμ†Œ 체계뢀터 closesocketκΉŒμ§€ ν•œλˆˆμ— 보기

AdaLovelace 2025. 4. 11. 17:52

λ‹¨μˆœν•œ λ™μž‘ μ΄ν•΄λΏλ§Œ μ•„λ‹ˆλΌ, μ˜€λ₯˜ 처리 흐름, μ „μ—­ λ³€μˆ˜ ν™œμš©, Winsock ν™•μž₯ ν•¨μˆ˜ μ μš©λ²•κΉŒμ§€ 싀무적인 츑면을 κ³ λ €ν•΄ μ •λ¦¬ν–ˆλ‹€.


βœ… μ—°μŠ΅λ¬Έμ œ 05-B: μ‚¬μš©μž μ •μ˜ ν•¨μˆ˜μ˜ 였λ₯˜ 처리


πŸ”§ μš”κ΅¬ 사항 μš”μ•½

  • f(int x) ν•¨μˆ˜λŠ” xκ°€ 음수면 μ‹€νŒ¨, κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ 성곡
  • μ‹€νŒ¨ μ‹œ errno μ „μ—­ λ³€μˆ˜μ— EINVAL μ„€μ •
  • 리턴 값은 성곡 μ‹œ 0, μ‹€νŒ¨ μ‹œ 1

πŸ“Œ κ΅¬ν˜„ μ½”λ“œ μ˜ˆμ‹œ

c
λ³΅μ‚¬νŽΈμ§‘
#include <stdio.h>
#include <errno.h>  // errno, EINVAL
#include <stdlib.h> // exit()

void err_quit(const char* msg) {
    perror(msg);
    exit(1);
}

int f(int x) {
    if (x >= 0) {
        errno = 0;
        return 0;
    } else {
        errno = EINVAL;  // Invalid argument
        return -1;
    }
}

int main() {
    int retval = f(-100);  // μ‹€νŒ¨ μ‹œλ„

    if (retval < 0)
        err_quit("f()");
    return 0;
}

πŸ’‘ μ‹€ν–‰ κ²°κ³Ό μ˜ˆμ‹œ

plaintext
λ³΅μ‚¬νŽΈμ§‘
f(): Invalid argument

errnoλŠ” C ν‘œμ€€μ˜ μ „μ—­ 였λ₯˜ μ½”λ“œ λ³€μˆ˜μ΄λ©°, μ‹œμŠ€ν…œ 호좜 였λ₯˜ 외에도 μ‚¬μš©μž μ •μ˜ ν•¨μˆ˜μ—μ„œ λ™μΌν•œ λ°©μ‹μœΌλ‘œ 처리 κ°€λŠ₯ν•˜λ‹€.

 


βœ… μ—°μŠ΅λ¬Έμ œ 06: WSASocket()으둜 TCP / UDP μ†ŒμΌ“ 생성


πŸ“Œ κ°œμš”

**WSASocket()**은 **socket()**κ³Ό μœ μ‚¬ν•˜μ§€λ§Œ ν™•μž₯ μ˜΅μ…˜, μ˜€λ²„λž© IO, ν”Œλž˜κ·Έ 지정이 κ°€λŠ₯ν•œ Winsock κ³ κΈ‰ ν•¨μˆ˜λ‹€.


πŸ”§ κΈ°λ³Έ μ‚¬μš© ν˜•μ‹

c
λ³΅μ‚¬νŽΈμ§‘
SOCKET WSASocket(
  int af,            // μ£Όμ†Œ 체계 (예: AF_INET)
  int type,          // μ†ŒμΌ“ νƒ€μž… (예: SOCK_STREAM)
  int protocol,      // ν”„λ‘œν† μ½œ (예: IPPROTO_TCP)
  LPWSAPROTOCOL_INFO lpProtocolInfo,
  GROUP g,
  DWORD dwFlags      // μ˜΅μ…˜ ν”Œλž˜κ·Έ
);


πŸ“Œ TCP/UDP μ†ŒμΌ“ 생성 예제 μ½”λ“œ

c
λ³΅μ‚¬νŽΈμ§‘
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")

void err_quit(const char* msg) {
    fprintf(stderr, "[였λ₯˜] %s: %d\\n", msg, WSAGetLastError());
    exit(1);
}

int main() {
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        err_quit("WSAStartup()");

    // TCP μ†ŒμΌ“
    SOCKET tcp_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    if (tcp_sock == INVALID_SOCKET)
        err_quit("WSASocket() - TCP");

    // UDP μ†ŒμΌ“
    SOCKET udp_sock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
    if (udp_sock == INVALID_SOCKET)
        err_quit("WSASocket() - UDP");

    printf("TCP μ†ŒμΌ“: %d\\n", (int)tcp_sock);
    printf("UDP μ†ŒμΌ“: %d\\n", (int)udp_sock);

    closesocket(tcp_sock);
    closesocket(udp_sock);
    WSACleanup();
    return 0;
}


βœ… 핡심 차이점 μš”μ•½: socket() vs WSASocket()

ν•­λͺ© socket() WSASocket()

κΈ°λ³Έ μš©λ„ λ‹¨μˆœ μ†ŒμΌ“ 생성 κ³ κΈ‰ κΈ°λŠ₯ 섀정이 ν•„μš”ν•œ μ†ŒμΌ“ 생성
ν™•μž₯ μ˜΅μ…˜ λΆˆκ°€ dwFlags ν”Œλž˜κ·Έλ‘œ μ„€μ • κ°€λŠ₯ (예: μ˜€λ²„λž©)
ν™œμš© 상황 λ‹¨μˆœ 톡신 ν”„λ‘œκ·Έλž¨ κ³ μ„±λŠ₯ μ„œλ²„, Overlapped I/O, QoS λ“± ν•„μš”μ‹œ

이 μ„Ήμ…˜μ—μ„œλŠ” λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ κ°€μž₯ μ€‘μš”ν•œ 기반 쀑 ν•˜λ‚˜μΈ "였λ₯˜ 처리(Error Handling)" κ°œλ…μ„ 닀룬닀. 특히 μ†ŒμΌ“ ν•¨μˆ˜μ˜ μ‹€νŒ¨ κ°€λŠ₯성이 높은 만큼, μœˆλ„μš°/λ¦¬λˆ…μŠ€ ν™˜κ²½μ—μ„œ 였λ₯˜λ₯Ό μ •ν™•νžˆ νƒμ§€ν•˜κ³ , μ‚¬μš©μžμ—κ²Œ λͺ…ν™•νžˆ μ „λ‹¬ν•˜λŠ” λ‘œμ§μ€ μ‹€λ¬΄μ—μ„œ 맀우 μ€‘μš”ν•˜λ‹€.


βœ… Chapter 02 - 01: 였λ₯˜ 처리 핡심 정리


πŸ“Œ λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 였λ₯˜ μ²˜λ¦¬κ°€ μ€‘μš”ν•œ 이유

  • λ„€νŠΈμ›Œν¬λŠ” μ˜ˆμΈ‘ λΆˆκ°€λŠ₯ν•œ μ™ΈλΆ€ ν™˜κ²½μ— 의쑴 (케이블, λΌμš°ν„°, 포트, λ°©ν™”λ²½ λ“±)
  • ν•¨μˆ˜ 호좜이 μ‹€νŒ¨ν•  κ°€λŠ₯성이 λ†’κΈ° λ•Œλ¬Έμ— λͺ¨λ“  μ£Όμš” μ†ŒμΌ“ ν•¨μˆ˜λŠ” λ°˜λ“œμ‹œ 였λ₯˜ 체크 ν•„μš”
  • 였λ₯˜ λ°œμƒ μ‹œ, μ½”λ“œλ‘œλŠ” μ›μΈλ§Œ 확인할 수 μžˆμœΌλ―€λ‘œ → μ‚¬μš©μžλ‚˜ κ°œλ°œμžκ°€ 이해할 수 μžˆλŠ” λ©”μ‹œμ§€λ‘œ 좜λ ₯ ν•„μš”

βœ… μ†ŒμΌ“ ν•¨μˆ˜ 였λ₯˜ 처리 μœ ν˜• (3κ°€μ§€)

μœ ν˜• 번호 μ„€λͺ… μ˜ˆμ‹œ

β‘  였λ₯˜ 처리 ν•„μš” μ—†μŒ 리턴값이 μ—†κ±°λ‚˜ μ‹€νŒ¨ κ°€λŠ₯μ„± μ—†μŒ closesocket() λ“± 일뢀 ν•¨μˆ˜
β‘‘ 리턴값 μžμ²΄κ°€ 였λ₯˜ 정보 포함 μ‹€νŒ¨ μ‹œ 0 λ˜λŠ” 음수 λ“±μœΌλ‘œ 리턴 WSAStartup()
β‘’ 리턴값과 였λ₯˜ μ½”λ“œ 뢄리 μ‹€νŒ¨ 확인 ν›„ μ˜€λ₯˜ μ½”λ“œ ν•¨μˆ˜ ν˜ΈμΆœ λŒ€λΆ€λΆ„μ˜ μ†ŒμΌ“ ν•¨μˆ˜ (socket()bind() λ“±)

주둜 μ‚¬μš©ν•˜λŠ” 방식은 β‘’λ²ˆ, 즉 "리턴값 확인 ν›„ → 였λ₯˜ μ½”λ“œ ν•¨μˆ˜ 호좜"이닀.


βœ… 1. μœˆλ„μš° μ†ŒμΌ“ 였λ₯˜ 처리 방식


πŸ“Œ λŒ€ν‘œ ν•¨μˆ˜: WSAGetLastError()

  • λŒ€λΆ€λΆ„μ˜ μ†ŒμΌ“ ν•¨μˆ˜λŠ” μ‹€νŒ¨ μ‹œ INVALID_SOCKET, SOCKET_ERROR λ“±μ˜ 값을 리턴
  • ꡬ체적인 였λ₯˜λŠ” **WSAGetLastError()**λ₯Ό 톡해 확인
cpp
λ³΅μ‚¬νŽΈμ§‘
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")

int main() {
    WSADATA wsa;
    int result = WSAStartup(MAKEWORD(2, 2), &wsa);

    if (result != 0) {
        printf("WSAStartup μ‹€νŒ¨: μ½”λ“œ %d\\n", result);
        return 1;
    }

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
        int errCode = WSAGetLastError();
        printf("μ†ŒμΌ“ 생성 μ‹€νŒ¨: μ½”λ“œ %d\\n", errCode);
    }

    WSACleanup();
    return 0;
}


πŸ“Œ 였λ₯˜ λ©”μ‹œμ§€ 좜λ ₯ ν•¨μˆ˜ (선택 적용)

μœˆλ„μš°μ—μ„œλŠ” 였λ₯˜ μ½”λ“œμ— λ”°λ₯Έ μ‹œμŠ€ν…œ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜λ €λ©΄ **FormatMessage()**λ₯Ό μ‚¬μš©ν•  수 있음:

cpp
λ³΅μ‚¬νŽΈμ§‘
#include <windows.h>

void print_error_message(DWORD errCode) {
    LPVOID msg;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, errCode, 0, (LPTSTR)&msg, 0, NULL);
    printf("였λ₯˜ λ©”μ‹œμ§€: %s\\n", (char*)msg);
    LocalFree(msg);
}


βœ… μš”μ•½ 흐름

plaintext
λ³΅μ‚¬νŽΈμ§‘
[μ†ŒμΌ“ ν•¨μˆ˜ 호좜]
    ↓
[λ¦¬ν„΄κ°’μœΌλ‘œ μ‹€νŒ¨ μ—¬λΆ€ 확인]
    ↓
[WSAGetLastError() 호좜]
    ↓
[였λ₯˜ μ½”λ“œ 좜λ ₯ λ˜λŠ” λ©”μ‹œμ§€ λ³€ν™˜]


πŸ“Œ 였λ₯˜ μ½”λ“œ μ˜ˆμ‹œ

μ½”λ“œ 의미

10013 κΆŒν•œ μ—†μŒ (Access denied)
10048 μ£Όμ†Œ 이미 μ‚¬μš© 쀑 (Address already in use)
10061 λŒ€μƒ μ—°κ²° κ±°λΆ€ (Connection refused)
10060 μ—°κ²° μ‹œκ°„ 초과 (Connection timed out)

전체 μ½”λ“œ λͺ©λ‘μ€ MSDNμ΄λ‚˜ WinError.hμ—μ„œ 확인 κ°€λŠ₯


μ•„λž˜λŠ” Chapter 02의 μ£Όμš” λ‚΄μš©μ„ κ°„κ²°ν•˜κ²Œ μ •λ¦¬ν•œ μš”μ•½λ³Έμ΄λ‹€. 핡심 ν•¨μˆ˜μ™€ κ°œλ…μ„ ν”Œλž«νΌ 별 차이와 ν•¨κ»˜ ꡬ쑰적으둜 μ •λ¦¬ν•΄λ‘μ—ˆμœΌλ‹ˆ, μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°μ˜ 초기 λ‹¨κ³„μ—μ„œ μ‹€μ „ μ μš©μ„ μœ„ν•œ λΉ λ₯Έ 참쑰용으둜 ν™œμš©ν•˜κΈ° μ’‹λ‹€.


βœ… Chapter 02 μš”μ•½: μ†ŒμΌ“ μ‹œμž‘ν•˜κΈ°


βœ… 01. μ˜€λ₯˜ 처리

ν•­λͺ© Windows Linux / POSIX

였λ₯˜ μ½”λ“œ μ–»κΈ° WSAGetLastError() μ „μ—­ λ³€μˆ˜ errno
였λ₯˜ λ©”μ‹œμ§€ μ–»κΈ° FormatMessage() strerror(errno) λ˜λŠ” perror()

λͺ¨λ“  μ£Όμš” μ†ŒμΌ“ ν•¨μˆ˜ (socket(), bind(), connect() λ“±)λŠ” μ‹€νŒ¨ μ‹œ 였λ₯˜ μ½”λ“œ λ°˜ν™˜ ν•„μš”

 


βœ… 02. μœˆμ† μ΄ˆκΈ°ν™”μ™€ μ’…λ£Œ (Windows ν•œμ •)

ν•¨μˆ˜ μ„€λͺ…

WSAStartup() μ†ŒμΌ“ μ‚¬μš©μ„ μœ„ν•œ 라이브러리 μ΄ˆκΈ°ν™” (Winsock 2.x μ‚¬μš©)
WSACleanup() μ†ŒμΌ“ μ‚¬μš© μ’…λ£Œ, λ¦¬μ†ŒμŠ€ λ°˜ν™˜

βœ… WSAStartup()은 λ°˜λ“œμ‹œ closesocket() ν›„ WSACleanup()으둜 정리해야 함

 


βœ… 03. μ†ŒμΌ“ 생성

ν•¨μˆ˜ μ„€λͺ…

socket() ν†΅μ‹ μš© μ†ŒμΌ“ 생성, λ‚΄λΆ€ λ¦¬μ†ŒμŠ€λ₯Ό ν• λ‹Ήν•˜κ³  ν•Έλ“€(SOCKET) 리턴

πŸ“Œ TCP/UDP μ„€μ • μ‘°ν•© μ˜ˆμ‹œ

ν”„λ‘œν† μ½œ μ£Όμ†Œ 체계 (af) μ†ŒμΌ“ νƒ€μž… (type) ν”„λ‘œν† μ½œ (protocol)

TCP AF_INETAF_INET6 SOCK_STREAM 0
UDP AF_INETAF_INET6 SOCK_DGRAM 0

protocol = 0이면 type에 따라 μžλ™ μ§€μ • (TCP: IPPROTO_TCP, UDP: IPPROTO_UDP)


βœ… 04. μ†ŒμΌ“ λ‹«κΈ°

ν”Œλž«νΌ ν•¨μˆ˜ λͺ… μ„€λͺ…

Windows closesocket() μ†ŒμΌ“ μ’…λ£Œ 및 λ¦¬μ†ŒμŠ€ ν•΄μ œ
Linux/Unix close() 파일 λ””μŠ€ν¬λ¦½ν„° 방식 μ†ŒμΌ“ μ’…λ£Œ

 


βœ… 싀무 μš”μ•½ 흐름 (Windows κΈ°μ€€)

plaintext
λ³΅μ‚¬νŽΈμ§‘
[WSAStartup()]  →  [socket()]  →  [μ‚¬μš©]  →  [closesocket()]  →  [WSACleanup()]

LinuxλŠ” WSAStartup() / WSACleanup() κ³Όμ • 없이 λ°”λ‘œ socket() ~ close() μ‚¬μš©


πŸ”š μΆ”κ°€ μš”μ•½ λ©”λͺ¨

  • socket() λ¦¬ν„΄κ°’은 μ‹€νŒ¨ μ‹œ INVALID_SOCKET (Windows) / 1 (Linux)
  • 리턴값 확인 ν›„ μ¦‰μ‹œ 였λ₯˜ μ½”λ“œ μΆ”μ ν•˜λŠ” μŠ΅κ΄€ μ€‘μš”
  • λͺ¨λ“  λ¦¬μ†ŒμŠ€λŠ” μ‚¬μš© ν›„ λ°˜λ“œμ‹œ ν•΄μ œ (closesocket() λ˜λŠ” close())

μ’‹μ•„, μ•„λž˜λŠ” μ—°μŠ΅λ¬Έμ œ 01~05-AκΉŒμ§€μ— λŒ€ν•œ μš”ꡬ사항 해석 → μ½”λ“œ 예제 → κ²°κ³Ό ν•΄μ„€ νλ¦„μœΌλ‘œ μ •λ¦¬ν•œ 완성도 높은 해섀이닀. Windows ν™˜κ²½μ—μ„œμ˜ Winsock ν”„λ‘œκ·Έλž˜λ°μ„ κΈ°μ΄ˆλΆ€ν„° μ‘μš©κΉŒμ§€ μ²΄κ³„μ μœΌλ‘œ λ‹€λ£° 수 μžˆλ„λ‘ μ„€κ³„ν–ˆμœΌλ©°, InitSocket 예제 μˆ˜μ •κ³Ό μ‚¬μš©μž μ •μ˜ ν•¨μˆ˜ 였λ₯˜ 처리 λ‘œμ§κΉŒμ§€ λͺ¨λ‘ ν¬ν•¨ν–ˆλ‹€.


βœ… μ—°μŠ΅λ¬Έμ œ 01: wsa λ³€μˆ˜μ˜ μ£Όμš” ν•„λ“œ 좜λ ₯


πŸ”§ μš”κ΅¬ 사항

  • WSADATA κ΅¬μ‘°μ²΄μ˜ λ‹€μŒ 4개 ν•„λ“œλ₯Ό 좜λ ₯
  • wVersionwHighVersionszDescriptionszSystemStatus
  • Winsock 1.1 버전 μš”μ²­(MAKEWORD(1,1)) μ‹œ κ°’ 비ꡐ

πŸ“Œ μ½”λ“œ 예제

cpp
λ³΅μ‚¬νŽΈμ§‘
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")

int main() {
    WSADATA wsa;
    int result = WSAStartup(MAKEWORD(1, 1), &wsa);
    if (result != 0) {
        printf("WSAStartup μ‹€νŒ¨: %d\\n", result);
        return 1;
    }

    printf("wVersion: %x\\n", wsa.wVersion);
    printf("wHighVersion: %x\\n", wsa.wHighVersion);
    printf("szDescription: %s\\n", wsa.szDescription);
    printf("szSystemStatus: %s\\n", wsa.szSystemStatus);

    WSACleanup();
    return 0;
}

πŸ’‘ κ²°κ³Ό μ˜ˆμ‹œ (버전 1.1 μš”μ²­ μ‹œ)

plaintext
λ³΅μ‚¬νŽΈμ§‘
wVersion: 101
wHighVersion: 202
szDescription: WinSock 2.0
szSystemStatus: Running

 

βœ… wVersion은 μš”μ²­λœ 버전, wHighVersion은 지원 κ°€λŠ₯ν•œ μ΅œλŒ€ 버전


βœ… μ—°μŠ΅λ¬Έμ œ 02-A / 02-B: UDP μ†ŒμΌ“ 생성


πŸ“Œ μ½”λ“œ 예제 (IPv4 기반 UDP)

cpp
λ³΅μ‚¬νŽΈμ§‘
SOCKET udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_sock == INVALID_SOCKET)
    err_quit("UDP μ†ŒμΌ“ 생성 μ‹€νŒ¨");

βœ… SOCK_DGRAM, protocol = 0 → UDP


βœ… μ—°μŠ΅λ¬Έμ œ 03-A / 03-B: IPv6 기반 TCP μ†ŒμΌ“ 생성


πŸ“Œ μ½”λ“œ 예제

cpp
λ³΅μ‚¬νŽΈμ§‘
SOCKET tcp6_sock = socket(AF_INET6, SOCK_STREAM, 0);
if (tcp6_sock == INVALID_SOCKET)
    err_quit("IPv6 TCP μ†ŒμΌ“ 생성 μ‹€νŒ¨");

βœ… AF_INET6으둜 μ£Όμ†Œ 체계λ₯Ό IPv6둜 μ„€μ •


βœ… μ—°μŠ΅λ¬Έμ œ 04-A / 04-B: IPv6 기반 UDP μ†ŒμΌ“ 생성


πŸ“Œ μ½”λ“œ 예제

cpp
λ³΅μ‚¬νŽΈμ§‘
SOCKET udp6_sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (udp6_sock == INVALID_SOCKET)
    err_quit("IPv6 UDP μ†ŒμΌ“ 생성 μ‹€νŒ¨");


βœ… μ—°μŠ΅λ¬Έμ œ 05-A: μ‚¬μš©μž μ •μ˜ ν•¨μˆ˜ 였λ₯˜ 처리 (WSASetLastError μ‚¬μš©)


πŸ”§ μš”κ΅¬ 사항

  • μž…λ ₯값이 음수면 SOCKET_ERROR λ°˜ν™˜, **WSASetLastError()**둜 였λ₯˜ μ½”λ“œ μ§€μ •
  • 성곡이면 0, 였λ₯˜μ½”λ“œλŠ” 0

πŸ“Œ μ½”λ“œ 예제

cpp
λ³΅μ‚¬νŽΈμ§‘
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")

void err_quit(const char* msg) {
    fprintf(stderr, "[였λ₯˜] %s: %d\\n", msg, WSAGetLastError());
    exit(1);
}

int f(int x) {
    if (x >= 0) {
        WSASetLastError(0);
        return 0;
    } else {
        WSASetLastError(WSAEINVAL);  // Invalid argument
        return SOCKET_ERROR;
    }
}

int main() {
    WSAStartup(MAKEWORD(2, 2), &(WSADATA){0});

    int retval = f(-100);
    if (retval == SOCKET_ERROR)
        err_quit("f()");

    WSACleanup();
    return 0;
}

πŸ’‘ 좜λ ₯ μ˜ˆμ‹œ

plaintext
λ³΅μ‚¬νŽΈμ§‘
[였λ₯˜] f(): 10022

βœ… 10022λŠ” WSAEINVAL에 ν•΄λ‹Ήν•˜λŠ” 였λ₯˜ μ½”λ“œ (Invalid argument)


πŸ”š 전체 μš”μ•½

문제 μ£Όμš” 포인트

01 WSADATA ν•„λ“œ 해석 및 버전 λ³€ν™” κ΄€μ°°
02 UDP μ†ŒμΌ“ 생성: SOCK_DGRAMAF_INET
03 IPv6 TCP μ†ŒμΌ“ 생성: AF_INET6SOCK_STREAM
04 IPv6 UDP μ†ŒμΌ“ 생성: AF_INET6SOCK_DGRAM
05 μ‚¬μš©μž μ •μ˜ 였λ₯˜ 처리 ν•¨μˆ˜: WSASetLastError() ν™œμš©

μ’‹μ•„, μ—¬κΈ°μ„œλŠ” μ‹€μŠ΅ 2-2의 핡심인 μ†ŒμΌ“ 생성과 λ‹«κΈ° (μœˆλ„μš° vs λ¦¬λˆ…μŠ€) λ₯Ό μ‹€μŠ΅ ν™˜κ²½μ— 맞게 λΆ„λ¦¬ν•˜μ—¬ κ΅¬μ„±ν•˜κ³ , μ‹€μ œ μ½”λ“œ μ„€λͺ…κΉŒμ§€ μ •λ¦¬ν•΄μ€„κ²Œ. λͺ©μ μ€ μ†ŒμΌ“μ„ λ§Œλ“€κ³  → 성곡 λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜κ³  → λ‹«λŠ” 일련의 과정을 톡해 μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°μ˜ κ°€μž₯ κΈ°λ³Έ 루틴을 μ²΄λ“ν•˜λŠ” 것이야.

βœ… μ‹€μŠ΅ 2-2: μ†ŒμΌ“ 생성과 λ‹«κΈ°


πŸ–₯️ Windows ν™˜κ²½: InitSocket.cpp

cpp
λ³΅μ‚¬νŽΈμ§‘
#include "..\\..\\Common.h"

int main(int argc, char* argv[]) {
    // 1. μœˆμ† μ΄ˆκΈ°ν™”
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        return 1;
    printf("[μ•Œλ¦Ό] μœˆμ† μ΄ˆκΈ°ν™” 성곡\\n");

    // 2. μ†ŒμΌ“ 생성 (IPv4, TCP)
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET)
        err_quit("socket()");
    printf("[μ•Œλ¦Ό] μ†ŒμΌ“ 생성 성곡\\n");

    // 3. μ†ŒμΌ“ λ‹«κΈ°
    closesocket(sock);

    // 4. μœˆμ† μ’…λ£Œ
    WSACleanup();

    return 0;
}

πŸ” 포인트 μš”μ•½

단계 ν•¨μˆ˜ μ„€λͺ…

1 WSAStartup() Winsock μ΄ˆκΈ°ν™” (ν•„μˆ˜)
2 socket() μ†ŒμΌ“ 생성 (IPv4 + TCP)
3 closesocket() μ†ŒμΌ“ μžμ› λ°˜ν™˜
4 WSACleanup() Winsock μ’…λ£Œ 및 정리

err_quit() ν•¨μˆ˜λŠ” Common.h에 μ •μ˜λœ μ‚¬μš©μž μ •μ˜ 였λ₯˜ 좜λ ₯ ν•¨μˆ˜. WSAGetLastError()λ₯Ό ν•¨κ»˜ 좜λ ₯함.


🐧 Linux ν™˜κ²½: InitSocket.cpp

cpp
λ³΅μ‚¬νŽΈμ§‘
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>     // close()
#include <sys/socket.h> // socket()
#include <netinet/in.h> // AF_INET

int main(int argc, char* argv[]) {
    // 1. μ†ŒμΌ“ 생성 (IPv4, TCP)
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket()");
        exit(1);
    }
    printf("[μ•Œλ¦Ό] μ†ŒμΌ“ 생성 성곡\\n");

    // 2. μ†ŒμΌ“ λ‹«κΈ°
    close(sock);

    return 0;
}

πŸ” Linux 포인트 차이

ν•­λͺ© μœˆλ„μš° λ¦¬λˆ…μŠ€

μ΄ˆκΈ°ν™” WSAStartup() ν•„μš” μ—†μŒ
μ’…λ£Œ WSACleanup() ν•„μš” μ—†μŒ
μ†ŒμΌ“ νƒ€μž… SOCKET (typedef) int
λ‹«κΈ° ν•¨μˆ˜ closesocket() close()
였λ₯˜ μ½”λ“œ WSAGetLastError() errno + perror()

πŸ”Ž μ½˜μ†” κ²°κ³Ό μ˜ˆμ‹œ

plaintext
λ³΅μ‚¬νŽΈμ§‘
[μ•Œλ¦Ό] μœˆμ† μ΄ˆκΈ°ν™” 성곡
[μ•Œλ¦Ό] μ†ŒμΌ“ 생성 성곡
→ 성곡 ν›„ μ’…λ£Œ

λ˜λŠ” Linuxμ—μ„œ:

bash
λ³΅μ‚¬νŽΈμ§‘
$ ./InitSocket
[μ•Œλ¦Ό] μ†ŒμΌ“ 생성 성곡


βœ… μš”μ•½ 흐름

plaintext
λ³΅μ‚¬νŽΈμ§‘
[μ†ŒμΌ“ 생성]
 ↓
[μ—λŸ¬ 확인]
 ↓
[정상 λ©”μ‹œμ§€ 좜λ ₯]
 ↓
[μžμ› 정리 (close)]


πŸ“Œ μ‹€μŠ΅ μ—°μž₯ 아이디어

  • AF_INET6 κΈ°λ°˜μœΌλ‘œ μ†ŒμΌ“ 생성 μ‹œλ„ν•΄λ³΄κΈ°
  • **SOCK_DGRAM**으둜 UDP μ†ŒμΌ“ μ‹€μŠ΅
  • μ‹€νŒ¨ μ‹œ 였λ₯˜ μ½”λ“œ 좜λ ₯ 및 λ©”μ‹œμ§€ν™” μ—°μŠ΅

이 μ ˆμ—μ„œλŠ” μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°μ—μ„œμ˜ "μ£Όμ†Œ 체계(Address Family)"와 "μ†ŒμΌ“ νƒ€μž…(Socket Type)"의 κ°œλ…κ³Ό 역할을 λͺ…ν™•νžˆ μ„€λͺ…ν•˜κ³  μžˆλ‹€. μ‹€λ¬΄μ μœΌλ‘œλŠ” socket() ν•¨μˆ˜μ˜ μ²« λ²ˆμ§Έμ™€ 두 번째 인수λ₯Ό μ •ν™•νžˆ μ΄ν•΄ν•˜κ³  μ„€μ •ν•˜λŠ” 것이 κ°€μž₯ 기초이자 핡심이닀. μ•„λž˜ λ‚΄μš©μ„ μš”μ•½κ³Ό 도식 μ€‘μ‹¬μœΌλ‘œ μž¬κ΅¬μ„±ν•΄ μ€„κ²Œ.

βœ… μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°μ—μ„œμ˜ μ£Όμ†Œ 체계와 μ†ŒμΌ“ νƒ€μž…


πŸ“Œ 1. μ£Όμ†Œ 체계 (Address Family)

κ°œλ…:

  • 톡신 λŒ€μƒμ˜ μ£Όμ†Œ ν˜•μ‹μ„ μ •μ˜
  • μ–΄λ–€ λ„€νŠΈμ›Œν¬ ν”„λ‘œν† μ½œ(IP, Bluetooth λ“±)을 μ‚¬μš©ν• μ§€λ₯Ό 선택함

λŒ€ν‘œ μ£Όμ†Œ 체계 κ°’

μ‚¬μš© λͺ©μ  μƒμˆ«κ°’ μ„€λͺ…

IPv4 톡신 AF_INET IPv4 μ£Όμ†Œ μ‚¬μš© (예: 192.168.0.1)
IPv6 톡신 AF_INET6 IPv6 μ£Όμ†Œ μ‚¬μš© (예: 2001:abcd::1)
Bluetooth 톡신 AF_BTH λΈ”λ£¨νˆ¬μŠ€ ν†΅μ‹ μš©
Unix Domain Socket AF_UNIX 둜컬 ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신 (λ¦¬λˆ…μŠ€ μ „μš©)

βœ… socket() ν•¨μˆ˜μ˜ μ²« 번째 인자둜 μ‚¬μš©λ¨


πŸ“Œ 2. μ†ŒμΌ“ νƒ€μž… (Socket Type)

κ°œλ…:

  • 데이터 전솑 방식 λ° μ‹ λ’°μ„± μ—¬λΆ€λ₯Ό κ²°μ •
  • TCP/UDP λ˜λŠ” λ‹€λ₯Έ ν”„λ‘œν† μ½œμ„ μ‚¬μš©ν•  λ•Œμ˜ 전솑 νŠΉμ„±μ„ μ •μ˜

λŒ€ν‘œ μ†ŒμΌ“ νƒ€μž… κ°’

μ†ŒμΌ“ νƒ€μž… νŠΉμ„± μ„€λͺ…

SOCK_STREAM μ—°κ²°ν˜•, μ‹ λ’°μ„± 보μž₯ (ex. TCP)
SOCK_DGRAM λΉ„μ—°κ²°ν˜•, μ‹ λ’°μ„± μ—†μŒ (ex. UDP)

βœ… socket() ν•¨μˆ˜μ˜ λ‘ 번째 인자둜 μ‚¬μš©λ¨


🧭 μ’…ν•© μ„€μ • κ°€μ΄λ“œ: TCP vs UDP

μ‚¬μš©ν•  ν”„λ‘œν† μ½œ μ£Όμ†Œ 체계 (af) μ†ŒμΌ“ νƒ€μž… (type)

TCP (IPv4/6) AF_INET λ˜λŠ” AF_INET6 SOCK_STREAM
UDP (IPv4/6) AF_INET λ˜λŠ” AF_INET6 SOCK_DGRAM

ν”„λ‘œν† μ½œ λ²ˆν˜ΈλŠ” 일반적으둜 0을 μž…λ ₯ν•˜λ©΄ type에 맞좰 μžλ™μœΌλ‘œ 섀정됨


πŸ“Œ 싀무 λ©”λͺ¨: νƒ€μž… ν˜Έν™˜μ„±κ³Ό SOCKET μ •μ˜

  • Windows:
    • **SOCKET**은 μ •μ˜λœ μžλ£Œν˜• (unsigned int λ“±) → closesocket() μ‚¬μš©
  • Linux:
    • **socket()**은 int νƒ€μž…을 λ°˜ν™˜ → close() μ‚¬μš©
  • ν˜Έν™˜μ„± 확보 방법:
  • cpp λ³΅μ‚¬νŽΈμ§‘ // Linuxμ—μ„œ Windows μ½”λ“œμ™€ λ™μΌν•˜κ²Œ μ‚¬μš© κ°€λŠ₯ν•˜λ„λ‘ λ§€ν•‘ typedef int SOCKET
    κ²°λ‘  μš”μ•½

 

plaintext
λ³΅μ‚¬νŽΈμ§‘
[1단계] μ£Όμ†Œ 체계 선택 (IPv4 vs IPv6 λ“±)
       ↓
[2단계] μ†ŒμΌ“ νƒ€μž… 선택 (TCP vs UDP λ“±)
       ↓
[3단계] socket() 호좜 → SOCKET ν•Έλ“€ λ°˜ν™˜

이 ꡬ쑰가 λ°”λ‘œ λͺ¨λ“  λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž¨μ˜ μ‹œμž‘μ μ΄ λ˜λŠ” μ†ŒμΌ“ 생성 κΈ°λ³Έ 곡식이야.


이번 μ ˆμ€ socket() ν•¨μˆ˜μ˜ μ„Έ 번째 인수인 ν”„λ‘œν† μ½œ μ§€μ • 방법, 그리고 μ†ŒμΌ“μ„ μ’…λ£Œν•  λ•Œ μ‚¬μš©ν•˜λŠ” closesocket() vs close() ν•¨μˆ˜μ— λŒ€ν•œ 정리λ₯Ό 닀루고 μžˆμ–΄. μ‹€λ¬΄μ—μ„œλ„ λΉˆλ²ˆν•˜κ²Œ λ°œμƒν•˜λŠ” ν˜Όμš© μΌ€μ΄μŠ€(AF vs PF)λ¦¬μ†ŒμŠ€ λˆ„μˆ˜ λ°©μ§€ κ΄€λ ¨ν•΄μ„œλ„ μ€‘μš”ν•œ κ°œλ…μ΄λ‹ˆ, μ‹€μŠ΅ κ΄€μ μœΌλ‘œ μž¬μ •λ¦¬ν•΄μ€„κ²Œ.


βœ… μ†ŒμΌ“ 생성 μ‹œ ν”„λ‘œν† μ½œ μ„€μ • + μ†ŒμΌ“ λ‹«κΈ°


πŸ“Œ 1. socket() ν•¨μˆ˜μ˜ μ„Έ 번째 인자: ν”„λ‘œν† μ½œ (Protocol)

πŸ”§ μ—­ν• 

  • λ™μΌν•œ μ£Όμ†Œ 체계(AF_)와 μ†ŒμΌ“ νƒ€μž…(SOCK_) μ‘°ν•©μ—μ„œ λͺ…ν™•ν•œ ν”„λ‘œν† μ½œ 선택이 ν•„μš”ν•  λ•Œ μ‚¬μš©

μ˜ˆμ‹œ: socket() ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜

c
λ³΅μ‚¬νŽΈμ§‘
int socket(int domain, int type, int protocol);

[ν‘œ 2-4] TCP와 UDP μ„€μ •

μ‚¬μš©ν•  ν”„λ‘œν† μ½œ μ£Όμ†Œ 체계 (domain) μ†ŒμΌ“ νƒ€μž… (type) ν”„λ‘œν† μ½œ (protocol)

TCP AF_INETAF_INET6 SOCK_STREAM IPPROTO_TCP (or 0)
UDP AF_INETAF_INET6 SOCK_DGRAM IPPROTO_UDP (or 0)

⚠️ μ‹€λ¬΄μ—μ„œλŠ” protocol μžλ¦¬μ— 보톡 0을 λ„£μœΌλ©΄, type에 따라 TCP/UDPκ°€ μžλ™μœΌλ‘œ 결정됨

πŸ“Œ ν”„λ‘œν† μ½œ κ°’ μƒμˆ˜ μš”μ•½

이름 κ°’ (보톡) μ„€λͺ…

IPPROTO_TCP 6 TCP ν”„λ‘œν† μ½œ
IPPROTO_UDP 17 UDP ν”„λ‘œν† μ½œ
0 μžλ™ μ§€μ • type κ°’ κΈ°μ€€ μžλ™ μ„€μ •

πŸ“Œ 2. AF_INET vs PF_INET

μ‹€μŠ΅ 쀑 ν—·κ°ˆλ¦΄ 수 μžˆλŠ” κ°œλ…, ν™•μ‹€νžˆ μ •λ¦¬ν•΄λ³΄μž.

ꡬ뢄 의미 μ‹€μ œ κ°’ 동일 μ‚¬μš© μœ„μΉ˜ (κ³Όκ±° κΈ°μ€€)

AF_INET Address Family (μ£Όμ†Œ 체계) βœ… κ°™μŒ μ†ŒμΌ“ μ£Όμ†Œ ꡬ쑰체 μ‚¬μš© (예: struct sockaddr_in)
PF_INET Protocol Family (ν”„λ‘œν† μ½œ 계열) βœ… κ°™μŒ socket() ν•¨μˆ˜μ—μ„œ μ‚¬μš©

βœ… μ§€κΈˆμ€ λŒ€λΆ€λΆ„μ˜ λ¬Έμ„œμ™€ μ½”λ“œμ—μ„œ AF_ κ³„μ—΄λ‘œ ν†΅μΌν•˜μ—¬ μ‚¬μš©


πŸ“Œ 3. μ†ŒμΌ“ λ‹«κΈ° (closesocket() vs close())

βœ… Windows

c
λ³΅μ‚¬νŽΈμ§‘
#include <winsock2.h>
int closesocket(SOCKET s);  // 리턴값: 성곡 0, μ‹€νŒ¨ SOCKET_ERROR

βœ… Linux

c
λ³΅μ‚¬νŽΈμ§‘
#include <unistd.h>
int close(int fd);          // 리턴값: 성곡 0, μ‹€νŒ¨ -1

πŸ” μ£Όμ˜ν•  점

ν•­λͺ© Windows Linux

μ†ŒμΌ“ νƒ€μž… SOCKET int (파일 λ””μŠ€ν¬λ¦½ν„°)
λ‹«κΈ° ν•¨μˆ˜ closesocket() close()
였λ₯˜ 확인 WSAGetLastError() errno / perror()

⚠️ close()둜 Winsock μ†ŒμΌ“μ„ μ’…λ£Œν•˜λ©΄ λ¦¬μ†ŒμŠ€ ν•΄μ œκ°€ λΆˆμ™„μ „ν•΄μ§ˆ 수 있음 → Windowsμ—μ„œλŠ” closesocket() ν•„μˆ˜


🧭 μ’…ν•© 흐름: μ†ŒμΌ“ 생성 ~ μ’…λ£Œ

c
λ³΅μ‚¬νŽΈμ§‘
// 1. μ†ŒμΌ“ 생성 (TCP μ˜ˆμ‹œ)
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // or 0

// 2. 톡신 μž‘μ—…

// 3. μ†ŒμΌ“ μ’…λ£Œ
closesocket(sock);    // Windows
close(sock);          // Linux


πŸ”š 정리 λ©”λͺ¨

κ°œλ… ν‚€μ›Œλ“œ μ„€λͺ…

μ£Όμ†Œ 체계 AF_INETAF_INET6 IPv4/IPv6용 μ£Όμ†Œ μ§€μ •
μ†ŒμΌ“ νƒ€μž… SOCK_STREAMSOCK_DGRAM TCP/UDP 전솑 μœ ν˜•
ν”„λ‘œν† μ½œ IPPROTO_TCPIPPROTO_UDP0 λͺ…μ‹œ λ˜λŠ” μžλ™ μ§€μ •
μ†ŒμΌ“ μ’…λ£Œ closesocket() vs close() ν”Œλž«νΌλ³„ μ’…λ£Œ 방식
AF vs PF μ‹€μ§ˆμ  차이 μ—†μŒ AF_INET μ‚¬μš© ꢌμž₯

이번 μ ˆμ€ μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°μ˜ κ°€μž₯ 기본이 λ˜λŠ” socket() ν•¨μˆ˜ 호좜 방식, 즉 μ†ŒμΌ“μ˜ μƒμ„±κ³Ό κ°œλ…μ— μ§‘μ€‘ν•˜κ³  μžˆμ–΄. Windows와 Linux κ°„μ˜ 차이점, 그리고 socket() ν•¨μˆ˜ 호좜 μ‹œ 전달해야 ν•˜λŠ” μ„Έ κ°€μ§€ 핡심 인자 — μ£Όμ†Œ 체계, μ†ŒμΌ“ νƒ€μž…, ν”„λ‘œν† μ½œ — 에 λŒ€ν•΄ μ•„μ£Ό μ€‘μš”ν•˜κ³ λ„ μ‹€μš©μ μΈ λ‚΄μš©μ„ 닀루고 μžˆμ–΄.

μ•„λž˜μ— κ΅¬μ‘°ν™”ν•΄μ„œ 핡심 μš”μ•½κ³Ό μ‹€μŠ΅ν˜• μ½”λ“œκΉŒμ§€ μ •λ¦¬ν•΄μ€„κ²Œ.


βœ… Chapter 03: μ†ŒμΌ“ 생성과 λ‹«κΈ° – 핡심 μš”μ•½


πŸ“Œ 1. μ†ŒμΌ“ μƒμ„±μ΄λž€?

  • socket() ν•¨μˆ˜λŠ” λ„€νŠΈμ›Œν¬ 톡신을 μœ„ν•œ ν•Έλ“€(=μ†ŒμΌ“ λ””μŠ€ν¬λ¦½ν„°) μ„ 생성
  • 이 핸듀은 λ„€νŠΈμ›Œν¬ μžμ›μ— λŒ€ν•œ μ ‘κ·Ό κΆŒν•œμ„ 의미
  • μƒμ„±λœ μ†ŒμΌ“ λ””μŠ€ν¬λ¦½ν„°λŠ” 이후 bind()connect()send()recv() λ“±μ˜ ν•¨μˆ˜μ— 전달

🧩 socket() ν•¨μˆ˜ ν”„λ‘œν† νƒ€μž… 비ꡐ

OS ν•¨μˆ˜ μ •μ˜ μ„€λͺ…

Windows SOCKET socket(int af, int type, int protocol); **SOCKET**은 별도 μ •μ˜λœ νƒ€μž…
Linux int socket(int domain, int type, int protocol); **int**ν˜• 파일 λ””μŠ€ν¬λ¦½ν„°

βœ… λ°˜ν™˜κ°’μ€ λ‘˜ λ‹€ μ†ŒμΌ“ ν•Έλ“€κ°’, μ‹€νŒ¨ μ‹œ INVALID_SOCKET (Windows) λ˜λŠ” -1 (Linux)


🧭 socket() ν•¨μˆ˜μ˜ μ„Έ κ°€μ§€ 인자

인자 이름 μ„€λͺ… 및 μ˜ˆμ‹œ κ°’

1 μ£Όμ†Œ 체계 AF_INETAF_INET6 (IPv4/6), AF_BLUETOOTHAF_UNIX
2 μ†ŒμΌ“ νƒ€μž… SOCK_STREAM (TCP), SOCK_DGRAM (UDP)
3 ν”„λ‘œν† μ½œ  

πŸ’» 예제 μ½”λ“œ – Windows (TCP μ†ŒμΌ“ 생성)

cpp
λ³΅μ‚¬νŽΈμ§‘
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")

int main() {
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        return 1;

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); // TCP
    if (sock == INVALID_SOCKET) {
        printf("μ†ŒμΌ“ 생성 μ‹€νŒ¨\\n");
        WSACleanup();
        return 1;
    }

    printf("μ†ŒμΌ“ 생성 성곡: %d\\n", (int)sock);
    closesocket(sock);
    WSACleanup();
    return 0;
}


🐧 예제 μ½”λ“œ – Linux (UDP μ†ŒμΌ“ 생성)

c
λ³΅μ‚¬νŽΈμ§‘
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int sock = socket(AF_INET, SOCK_DGRAM, 0); // UDP
    if (sock < 0) {
        perror("μ†ŒμΌ“ 생성 μ‹€νŒ¨");
        exit(1);
    }

    printf("μ†ŒμΌ“ 생성 성곡: %d\\n", sock);
    close(sock);
    return 0;
}


πŸ”š 정리: μ†ŒμΌ“ 생성 핡심 포인트

ν•­λͺ© λ‚΄μš©

ν”Œλž«νΌ 차이 Windows: WSAStartup() ν•„μˆ˜ / λ¦¬λˆ…μŠ€λŠ” μ—†μŒ
리턴값 μ‹€νŒ¨ μ‹œ Windows: INVALID_SOCKET, Linux: -1
ν΄λ‘œμ§• Windows: closesocket() / Linux: close()
일반 μ„€μ • TCP: AF_INETSOCK_STREAM0 / UDP: AF_INETSOCK_DGRAM0