[네트워크]-소켓 통신(2) TCP 소켓 통신의 흐름

Shim31·2023년 10월 2일
0

Network

목록 보기
4/6

1. socket() 시스템 콜

소켓을 만드는 시스템 콜

int socket_descriptor;
socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);

socket ( domain, type, protocol ); → 리턴값은 파일 디스크립터

DomainIPv4, IPv6중 무엇을 사용할지 결정
Typestream, datagram 소켓 중 선택
Protocol0, 6, 17 중 0을 넣으면 시스템이 프로토콜을 선택하며, 6이면 tcp, 17이면 udp
💜 **즉, IPv4, IPv6 중 어떤 통신을 위해 사용할지, TCP UDP 중 어떤 것을 사용할지 틀을 만들어주는 과정**

Socket()의 리턴값은 파일 디스크립터

  1. 리눅스에서 모든 것을 파일로 취급함
  2. 소켓도 역시 파일로 취급함
  3. 웹 서버 프로세스가 시스템 콜을 사용할 때, 대상 파일의 파일 디스크립터를 파라미터로 전송
  4. 이때, 파일 디스크립터가 소켓의 파일 디스크립터인 경우 데이터 송신, 수신 동작을 하게 됨

2. bind() 시스템 콜

생성한 소켓에 실제 아이피 주소와 포트 번호를 부여하는 시스템 콜

bind(sockfd, sockaddr, socklen_t)

sockfd바인딩을 할 소켓의 파일 디스크립터
sockaddr소켓에 바인딩할 아이피 주소, 포트 번호를 담은 구조체
socklen_t위 구조체의 메모리 크기
  • 파라미터에 소켓의 파일 디스크립터를 포함 OS에게 어떤 소켓에 IP 주소와 포트 번호를 부여할지 알려줘야 함
  • → bind() 시스템 콜은 서버에서만 사용 클라이언트는 통신 시 포트 번호가 자동으로 부여됨

3. listen() 시스템 콜

연결 요청을 받아들이는 시스템 콜

연결 지향인 TCP에서만 사용하는 시스템 콜

**listen ( sockfd, backlog )**

sockfd소켓의 파일 디스크립터
backlog연결요청을 받아줄 크기 = TCP의 백로그 큐의 크기
  • 파라미터로 받은 파일 디스크립터에 해당하는 소켓을 클라이언트의 연결 요청을 받아들임
  • 최대로 받아주는 크기를 backlog로 설정 backlog = TCP 백로그 큐의 크기

연결 요청을 받아들이는 법

listen() 시스템 콜 → 파라미터로 받은 백로그 크기만큼 백로그 큐를 만드는 시스템 콜

  1. 서버 측 소켓은 listen() 이후 대기 상태

  2. 클라이언트의 연결 요청을 받아주기 위해 백로그 큐를 가진 상태로 대기함

    실제로 서버에 많은 요청이 오고 이 요청들은 모두 백로그 큐에 저장이 됨

    💡 **클라이언트 소켓을 통해 처음으로 서버에 요청을 하여 백로그 큐에 들어갈 때 *syn* 요청을 보냄**

    3-way handshake의 1단계

    3-way handshake

  1. 큐에서 대기 중인 요청은 accept() 시스템 콜을 이용해 처리

4. accept() 시스템 콜

backlog queue에서 syn을 보내와 대기 중인 요청을 선입선출로 연결을 해줌

**int accept( sockfd, sockaddr, soklen_t );**

sockfd백로그 큐의 요청을 받아들이기 위한 소켓의 파일 디스크립터
sockaddr선입선출로 빼온 연결 요청에서 알아낸 클라이언트의 주소 정보
socklen_t위 구조체의 메모리 크기
  • 클라이언트의 주소 정보 (클라이언트의 아이피 주소, 포트번호) → 이 값은 백로그 큐의 가장 앞에 있는 연결 요청 구조체에서 알아냄
  • accept() 시스템 콜의 리턴 값 새로운 소켓의 파일 디스크립터

4.1 TCP 3-way handshake

3-way handshake


4.2 accept 시스템 콜 이후 멀티 프로세스/멀티 쓰레드

사용 이유

accept 시스템 콜 이후, 곧바로 잔여 3-way handshake 이후 데이터 송/수신이 이루어 지는 것이 아님

멀티 프로세스/멀티 쓰레드의 테크닉이 들어감

why?

  1. 서버 → 하나의 프로세스
  2. 서버는 클라이언트의 수많은 요청을 받는 상황
  3. 로그 큐의 가장 앞에 있던 클라이언트의 요청을 받고 응답까지 다 주고 다시 다음 요청을 받아준다면

→ 엄청난 병목이 생김

💡 **서버는 연결 요청을 받는 부분 따로, 이후 응답까지 주는 부분을 따로 나누게 됨**

즉, 서버는 연결을 받는 부분, 응답을 주는 부분이 병렬적으로 이루어짐


0개의 댓글