[TIL/크래프톤 정글] DAY 56

배재준·2025년 5월 5일

크래프톤 정글 - TIL

목록 보기
49/93
post-thumbnail

2025.05.04

TIL(TODAY I LEARN)


  • 오늘한 내용 : CS - 네트워크 프로그래밍 - 11.1 ~ 11.4

  • WEEK08: BSD소켓, IP, TCP, HTTP, file descriptor, DNS


11.1 클라이언트-서버 프로그래밍 모델

  • 컴퓨터 네트워크는 클라이언트-서버 모델을 기반으로 구성됨.
  • 클라이언트: 서비스를 요청하는 쪽 (ex: 브라우저)
  • 서버: 요청을 받고 응답을 처리하는 쪽 (ex: 웹 서버, DB 서버)
  • 서로 간의 데이터 교환은 소켓(socket)을 통해 이뤄짐.

클라이언트 특징

  • 서버에 연결을 요청하고
  • 결과를 기다리거나 처리
  • 일반적으로 짧게 연결, 일회성 통신

서버 특징

  • 항상 실행 중
  • 특정 포트를 열고 연결을 기다림
  • 여러 클라이언트 요청을 동시 처리

11.2 네트워크

  • 네트워크(Network)는 여러 호스트(host)들이 링크(link)로 연결되어 통신할 수 있도록 해주는 시스템.
  • 현대 컴퓨터 시스템은 기본적으로 네트워크를 통해 연결되며, 모든 프로그램도 이를 전제로 설계됨.
구성 요소설명
호스트 (Host)네트워크에 연결된 컴퓨터 (IP 주소 가짐)
링크 (Link)호스트/라우터 간 실제 연결 (이더넷, Wi-Fi 등)
라우터 (Router)패킷을 목적지로 전달하는 중간 장치
패킷 (Packet)데이터를 쪼갠 전송 단위 (헤더 + 본문)

TCP/IP 계층 구조 요약

계층역할주요 예시
응용 계층사용자 앱 – 데이터 생성HTTP, DNS
전송 계층프로세스 간 연결TCP, UDP
인터넷 계층호스트 간 라우팅IP
링크 계층홉 간 실제 전송Ethernet (MAC 주소)

데이터 전송: 캡슐화 구조

데이터는 위에서 아래로 내려가며 캡슐화됨:

HTTP 데이터
↓ (TCP 헤더 추가)
TCP 세그먼트
↓ (IP 헤더 추가)
IP 패킷
↓ (MAC 헤더 추가)
이더넷 프레임 → 네트워크로 전송

IP 주소 vs MAC 주소

항목IP 주소MAC 주소
목적최종 호스트 식별홉 단위 전송 대상
범위논리적, 전 세계 고유물리적, 네트워크 인터페이스
라우팅라우터가 IP로 다음 경로 판단NIC가 MAC으로 다음 홉 전달
변동성DHCP 등으로 변경 가능고정 (수정 가능)

홉 바이 홉 전송 (Hop-by-hop)

  • 패킷은 라우터를 여러 개 거쳐서 목적지에 도착
  • 각 라우터는 다음 목적지 MAC 주소를 알아야 하므로,
  • ARP(Address Resolution Protocol) 를 사용해 MAC 주소를 동적으로 조회함

Ethernet이란?

  • 링크 계층 프로토콜 중 가장 널리 쓰이는 방식
  • MAC 주소(48비트) 기반으로 프레임을 전송
  • 구조:
    [MAC 헤더][IP 헤더][TCP 헤더][데이터][체크섬]

혼잡(Congestion)과 신뢰성 문제

  • 라우터 큐가 꽉 차면 → 패킷 손실, 재전송, 지연
  • IP는 신뢰성 없음 (비보장, 무연결)
  • TCP가 이를 해결: 재전송, 순서 보장, 흐름 제어 등

프로그래머 관점 정리

  • 네트워크 내부 구조는 운영체제가 관리
  • 우리는 소켓 API를 통해 통신만 신경 쓰면 됨
  • read(), write()를 네트워크 소켓에도 사용 가능 → 파일처럼 사용

11.3 글로벌 IP 인터넷

  • 인터넷은 전 세계 호스트를 연결한 공용 패킷 교환 네트워크
  • 라우터와 링크를 통해 구성됨
  • 프로토콜은 TCP/IP 기반

11.3.1 IP Addresses (IP 주소)

  • IP 주소는 인터넷에서 호스트(컴퓨터, 서버 등)를 식별하는 고유한 주소
  • 현재는 IPv4(32비트) 주소가 널리 사용됨 → 예: 152.46.7.80

IP 주소 형식 (IPv4)

  • 32비트 정수로 표현됨
  • IP는 “종단 간 통신에서 위치를 지정하는 주소
  • 일반적으로 10진수 4개를 점(.)으로 구분한 형식 사용
    • 예: 192.168.0.1 → 내부적으로는 32비트로 저장됨
  • 각 숫자는 0~255 범위 (1바이트)
  • 내부적으로는 host byte order ↔ network byte order 전환 필요 → 함수 htonl(), ntohl() 등이 있음

    엔디안

    • 컴퓨터가 여러 바이트로 구성된 데이터를 메모리에 저장하는 순서

    • 대표적으로 2가지 방식:

      종류설명예시 (0x12345678 저장 시)
      빅 엔디안 (Big-endian)가장 큰 바이트(상위 바이트)를 앞에 저장12 34 56 78
      리틀 엔디안 (Little-endian)가장 작은 바이트(하위 바이트)를 앞에 저장78 56 34 12
    • 네트워크는 무조건 빅 엔디안

      함수설명
      htonl(x)host → network (32비트 정수)
      htons(x)host → network (16비트 정수)
      ntohl(x)network → host (32비트 정수)
      ntohs(x)network → host (16비트 정수)

11.3.2 인터넷 도메인 이름

  • IP 주소는 사람이 외우기 어렵다 → 그래서 사람이 기억하기 쉬운 이름(domain name) 사용
    • 예: www.cmu.edu, google.com
  • 도메인 이름은 인터넷 자원을 식별하는 텍스트 기반 주소

DNS (Domain Name System)

  • DNS는 도메인 이름을 IP 주소로 변환해주는 분산 데이터베이스 시스템
  • 전 세계적으로 분산된 수많은 DNS 서버들이 계층적 구조로 협력

11.3.3 인터넷 연결

  • 클라이언트 프로그램이 서버와 통신하기 위한 준비 절차를 말함
  • IP 주소, 포트 번호, 소켓(socket) 등을 사용해 TCP 연결을 맺음
  • 연결(connection)은 점대점(point-to-point) 구조로, 두 프로세스를 연결
  • 풀 듀플렉스(full duplex) 구조 → 양방향 전송이 동시에 가능
  • 신뢰성 있음: 전송된 바이트는 순서대로 정확히 도착함 (TCP 특성)

소켓(socket): 연결의 끝점

  • 소켓은 연결의 끝점(end point) 역할
  • 소켓 주소는 (IP 주소, 포트 번호)의 쌍으로 구성됨 → address:port

포트 번호

  • 포트는 하나의 호스트 안에서 여러 프로세스를 구분하는 수단
  • 클라이언트:
    • 커널이 자동으로 임시 포트(ephemeral port) 할당
  • 서버:
    • 고정된 잘 알려진 포트(well-known port) 사용
    • 예: HTTP는 80, SMTP는 25
  • 포트 번호 ↔ 서비스 이름 매핑은 /etc/services 파일에 저장됨

소켓 쌍(socket pair)

  • 하나의 연결은 두 소켓 주소 쌍으로 고유하게 식별됨

(cliaddr:cliport, servaddr:servport)

예시:

  • 클라이언트: 128.2.194.242:51213 (임시 포트)
  • 서버: 208.216.181.15:80 (HTTP 서비스 포트)

11.4 소켓 인터페이스

  • 소켓(socket): 프로세스 간 네트워크 통신을 위한 양 끝점(endpoint)
  • 운영체제는 소켓을 파일 디스크립터처럼 다룸
  • 소켓 인터페이스는 UNIX가 제공하는 네트워크 시스템 콜 집합

TCP 소켓 흐름

클라이언트와 서버는 서로 다른 순서로 함수 호출:

  • 클라이언트
    1. socket() – 소켓 생성
    2. connect() – 서버에 연결 요청
    3. read() / write() – 데이터 송수신
  • 서버
    1. socket() – 소켓 생성
    2. bind() – IP 주소와 포트를 소켓에 바인딩
    3. listen() – 연결 요청 대기
    4. accept() – 클라이언트 연결 수락
    5. read() / write() – 데이터 송수신

11.4.1 소켓 주소 구조체

  • sockaddr 구조체: 소켓 주소 정보를 담는 범용 구조체
  • sockaddr_in: IPv4 주소용 구조체
    struct sockaddr_in {
        uint16_t        sin_family; // AF_INET
        uint16_t        sin_port;   // 포트 번호(빅엔디안)
        struct in_addr  sin_addr;   // IP 주소
        unsigned char   sin_zero[8];// 패딩
    };
    

11.4.2 socket 함수

int socket(int domain, int type, int protocol);
인자설명
domain주소 체계: IPv4는 AF_INET
type전송 방식: TCP는 SOCK_STREAM, UDP는 SOCK_DGRAM
protocol보통 0 (자동 선택)
  • 새로운 소켓을 생성하고, 파일 디스크립터 반환

11.4.3 connect 함수 (클라이언트용)

int connect(int sockfd, struct sockaddr *addr, socklen_t addrlen);
  • 서버의 IP와 포트에 연결 요청
  • addr은 보통 sockaddr_insockaddr*로 캐스팅
  • 연결 성공 시 TCP 3-way handshake 완료됨
  • 클라이언트에서만 사용

11.4.4 bind 함수 (서버용)

int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen);
  • 소켓에 로컬 IP 주소와 포트 번호를 연결
  • INADDR_ANY를 쓰면 모든 NIC에서의 연결 수락
  • 서버는 이걸로 “내가 어떤 포트로 연결 받을지” 설정함

11.4.5 listen 함수

int listen(int sockfd, int backlog);
  • 연결 요청을 받을 수 있게 소켓을 수동 대기(passive open) 상태로 바꿈
  • backlog: 대기열 크기 (보통 8~128)
  • bind() 후 호출해야 함

11.4.6 accept 함수

int accept(int listenfd, struct sockaddr *addr, socklen_t *addrlen);
  • 클라이언트 연결 요청을 수락
  • 새로운 연결 전용 소켓을 반환함 (listen 소켓과 별개!)
  • addr에는 클라이언트의 주소 정보가 들어감
  • 반환된 소켓으로 클라이언트와 read()/write() 가능

11.4.7 호스트와 서비스 변환

getaddrinfo() 함수

  • 도메인 이름(www.google.com)과 포트 번호("80")를 소켓 주소 구조체(struct sockaddr)로 변환해주는 함수
int getaddrinfo(const char *hostname, const char *port,
                const struct addrinfo *hints,
                struct addrinfo **result);
  • 사용 예시
struct addrinfo *res, hints;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("www.google.com", "80", &hints, &res);
  • res는 연결에 사용할 수 있는 소켓 주소 리스트를 가리킴
  • 결과는 freeaddrinfo(res)로 해제해야 함
  • 내부적으로 DNS 질의 + IP 주소 + 포트 정보 세팅까지 자동 처리

11.4.8 소켓 인터페이스를 위한 도움 함수들

반복되는 소켓 코드를 줄이기 위한 헬퍼 함수 정의

책에서는 다음 두 함수를 만들어서 클라이언트/서버 코드 간결화함:

open_clientfd(char *hostname, char *port)

  • 클라이언트 소켓을 열고 서버에 connect()까지 수행
  • 내부에서 getaddrinfo() + socket() + connect() 전부 처리
  • 성공 시 연결된 소켓 디스크립터 반환

open_listenfd(char *port)

  • 서버용 리슨 소켓을 생성하고, 포트에 바인딩 + listen()까지 수행
  • 내부에서 getaddrinfo() + socket() + bind() + listen() 처리
함수용도내부에서 하는 일
getaddrinfo()도메인 이름 → 소켓 주소 변환DNS + 포트 세팅
open_clientfd()클라이언트 소켓 생성 및 연결getaddrinfo + socket + connect
open_listenfd()서버 리슨 소켓 설정getaddrinfo + socket + bind + listen

0개의 댓글