소켓(Socket)

소켓은 네트워크 상에서 수행되는 두 프로그램 간의 양방향 통신 링크의 한쪽 끝 단을 의미한다.
소켓은 프로세스가 네트워크를 통해 데이터를 송수신하기 위한 실제적인 창구 역할을 한다.
운영체제는 소켓을 통해 네트워크 통신을 위한 인터페이스를 제공한다.

소켓의 구성 요소

소켓은 다음 세 가지 요소로 구성된다:

  1. 프로토콜: 데이터 전송을 위한 표준 집합 규칙 (예: TCP/IP, UDP/IP)
  2. IP 주소: 서버 또는 클라이언트의 주소
  3. 포트 번호: 통신을 사용하는 애플리케이션을 식별하는 번호

소켓의 특징

  • 프로토콜, IP 주소, 포트 번호로 정의된다.
  • 서버 소켓과 클라이언트 소켓으로 구분된다.
  • 실시간 데이터 전송에 적합하다.

소켓 통신의 장점

  • 실시간 양방향 통신이 가능하다.
  • 서버와 클라이언트 간 지속적인 연결을 유지할 수 있다.

소켓 통신의 단점

  • HTTP 통신에 비해 구현이 복잡할 수 있다.
  • 지속적인 연결 유지로 인한 리소스 소비가 있을 수 있다.

소켓의 종류

소켓은 크게 두 가지 유형으로 나눌 수 있다:

  1. 스트림 소켓(SOCK_STREAM)
    • TCP를 사용하는 연결 지향형 소켓
    • 연결 지향적이며 양방향으로 바이트 스트림을 전송한다.
    • 오류 수정, 전송 처리, 흐름 제어를 보장한다.
    • 데이터의 경계가 없는 바이트 스트림 서비스를 제공한다.
    • 웹 서버, 데이터베이스 연결 등에 사용
  2. 데이터그램 소켓(SOCK_DGRAM)
    • UDP를 사용하는 비연결형 소켓
    • 비연결형 소켓이다.
    • 데이터의 크기에 제한이 있으며, 전달이 보장되지 않는다.
    • 데이터 경계를 구분하는 데이터그램 서비스를 제공한다.
    • 실시간 스트리밍, 게임 등에 사용

소켓 통신의 기본 흐름

  • 서버와 클라이언트 간의 연결이 성립되면 양방향으로 데이터 통신이 가능하다.
  • TCP 연결의 경우, 연결 요청 시 3-way handshake 과정이 진행된다.
  • 서버는 여러 클라이언트의 연결 요청을 처리하기 위해 대기열(queue)을 만들어 관리한다.
  • 실제 데이터 송수신은 accept() 함수로 생성된 새로운 소켓을 통해 이루어진다.

이러한 기본 흐름을 통해 소켓은 네트워크 상에서 프로세스 간 통신의 종착점 역할을 하며, 전송 계층과 응용 프로그램 사이의 인터페이스로 작동한다.

소켓 통신의 기본 흐름은 서버와 클라이언트 간의 상호작용으로 이루어진다. :

  • 서버 측 흐름

    1. 소켓 생성: socket() 함수를 사용하여 소켓을 생성한다.
    2. 바인딩: bind() 함수로 소켓에 IP 주소와 포트 번호를 할당한다.
    3. 연결 대기: listen() 함수를 호출하여 클라이언트의 연결 요청을 기다린다.
    4. 연결 수락: accept() 함수로 클라이언트의 연결 요청을 수락한다. 이 때 새로운 소켓이 생성되어 클라이언트와의 통신에 사용된다.
    5. 데이터 송수신: send()/recv() 함수를 사용하여 클라이언트와 데이터를 주고받는다.
    6. 연결 종료: close() 함수로 소켓을 닫는다.
  • 클라이언트 측 흐름

    1. 소켓 생성: socket() 함수를 사용하여 소켓을 생성한다.
    2. 연결 요청: connect() 함수를 호출하여 서버에 연결을 요청한다.
    3. 데이터 송수신: send()/recv() 함수를 사용하여 서버와 데이터를 주고받는다.
    4. 연결 종료: close() 함수로 소켓을 닫는다.

TCP 소켓의 경우:

  1. 서버 소켓 생성
  2. 서버 소켓 바인딩 (IP주소와 포트번호 할당)
  3. 연결 대기 (Listen)
  4. 클라이언트의 연결 요청 수락 (Accept)
  5. 데이터 송수신
  6. 연결 종료

UDP 소켓의 경우:

  1. 소켓 생성
  2. 소켓 바인딩
  3. 데이터 송수신
  4. 소켓 종료

주요 소켓 함수

소켓의 작동 방식에서 각 함수는 다음과 같은 역할을 수행한다:

  • 서버 측 함수

    1. socket(): 소켓을 생성한다. 통신의 첫 단계로, 네트워크 통신을 위한 엔드포인트를 만든다.
    2. bind(): 생성된 소켓에 IP 주소와 포트 번호를 할당한다. 이를 통해 특정 주소와 포트에서 들어오는 연결을 수신할 수 있게 된다.
    3. listen(): 클라이언트의 연결 요청을 대기하는 상태로 소켓을 변경한다. 연결 요청을 수신할 준비가 되었음을 나타낸다.
    4. accept(): 클라이언트의 연결 요청을 수락한다. 새로운 소켓을 생성하여 클라이언트와의 통신에 사용한다.
  • 클라이언트 측 함수

    1. socket(): 서버와 마찬가지로 소켓을 생성한다.
    2. connect(): 서버에 연결을 요청한다. 서버의 IP 주소와 포트 번호를 지정하여 연결을 시도한다.
  • 공통 함수

    1. send()/recv(): 데이터를 송수신한다. 연결된 소켓을 통해 실제 데이터 통신이 이루어진다.
    2. close(): 소켓을 닫는다. 통신이 완료되면 소켓을 종료하여 리소스를 해제한다.

이러한 함수들의 호출 순서와 역할을 통해 소켓은 네트워크 상에서 두 프로그램 간의 양방향 통신을 가능하게 한다.
서버는 연결을 수신하고 관리하는 역할을, 클라이언트는 연결을 요청하고 데이터를 교환하는 역할을 수행한다.

소켓의 작동 방식과 함수 호출 과정

호출 과정:

  1. 서버는 socket() → bind() → listen() 순으로 초기화
  2. 클라이언트는 socket() → connect() 로 연결 시도
  3. 서버는 accept()로 연결 수락
  4. send()/recv() 를 통한 양방향 통신
  5. close()로 연결 종료

참고 및 출처