티스토리 뷰

[ TCP/IP의 데이터를 전기 신호로 만들어 보낸다 ]

1. 소켓을 작성한다

프로토콜 스택의 내부 구성

  • 위부터 아래로 데이터 송수신의 일을 의뢰한다.
  • 가장 위에 네트워크 어플리케이션이 위치해있고 브라우저, 웹 서버, 메일 서버 등이 여기에 해당된다.
    • 어플리케이션의 아랫부분에는 Socket 라이브러리가 있으며, 이 안에 리졸버가 내장되어 있다.
  • OS의 내부에 프로토콜 스택이 있고, TCP/UDP 프로토콜을 사용해 데이터 송수신을 담당하는 부분이 있고, 이 둘이 의뢰를 받아 송수신 동작을 실행한다.
    • TCP: 브라우저나 메일 등에서 사용
    • UDP: DNS 서버 조회 등 짧은 제어용 데이터 송수신의 경우 사용
  • IP 프로토콜: 패킷 송수신 동작을 제어
    • 인터넷에서 데이터를 운반할 때는 데이터를 작게 나누어 패킷 형태로 운반한다.
    • 이 패킷을 통신 상대까지 운반하는 것이 IP의 주 역할.
    • IP에는 ICMP, ARP 프로토콜을 다루는 부분이 포함됨
      • ICMP: 패킷 운반 중 발생 오류나 제어용 메시지를 통지할 때 사용
      • ARP: IP 주소에 대응하는 이더넷의 MAC 주소를 조사할 때 사용
  • LAN 드라이버: LAN 어댑터의 하드웨어를 제어

소켓의 실체는 통신 제어용 제어 정보

  • 프로토콜 스택 내부에는 통신 상대 IP 주소, 포트 번호, 통신 동작 상태 등을 기록하는 메모리 영역을 갖고 있다.
  • 본래 소켓은 실체가 없는 개념적인 것이므로, 이 메모리가 즉 소켓의 실체라고 생각해도 무관하다.
  • 프로토콜 스택은 소켓에 기록된 제어 정보를 참조하며 수행된다.

Socket을 호출했을 때의 동작

  • 어플리케이션이 socket을 호출하여 소켓 생성을 의뢰하면, 프로토콜 스택은 한 개의 소켓을 만든다.
  • 프로토콜 스택은 소켓 한 개 분량의 메모리 영역을 확보하고 초기 상태라는 것을 기록한다.
  • 소켓을 만들면 해당 소켓을 가르키는 디스크립터를 어플리케이션에게 알려주며, 디스크립터는 프로토콜 스택 내부의 많은 소켓 중 본인의 소켓 정보를 찾을 수 있는 번호표 같은 정보이다.

2. 서버에 접속한다

접속의 의미

  • 소켓을 만들면 애플리케이션은 connect를 호출하고 나면, 프로토콜 스택이 본인 소켓을 서버측 소켓에 접속을 시도한다.
  • 이더넷이나 통신 회선은 항상 케이블이 연결되어 있어 언제나 신호를 보낼 수 있기에 데이터를 신호로 변환해 송신만 하면 언제든 통신이 가능하다.
  • 다만, 소켓 생성 직후에 애플리케이션에서 송신 의뢰가 오면 통신을 할 수 없다.
    • 소켓을 만든 직후에는 아무 것도 기록되어 있지 않아 통신 상대를 알 수 없기 때문이다.
    • 때문에 서버의 IP 주소나 포트 번호를 프로토콜 스택에 알리는 동작이 필요하고, 이는 접속 동작에서 하나의 역할이기도 하다.
  • 접속 동작의 첫 번째 동작은 상대와 제어 정보를 주고받아 소켓에 필요한 정보를 기록하고 데이터 송수신이 가능한 상태로 만드는 것이다.
  • 데이터 송수신 동작을 실행하기 위해선 데이터를 일시적으로 담는 버퍼 메모리라는 메모리 영역이 필요하다.
  • 버퍼 메모리 확보 또한 접속 동작을 할 때 실행된다.

맨 앞부분에 제어 정보를 기록한 헤더를 배치한다.

  • TCP 헤더에 대한 포맷은 고정되어 있으며, 접속, 송수신, 연결 끊기의 각 단계에서 클라이언트와 서버간의 통신마다(패킷 맨 앞부분에) 이 제어 정보를 부가한다.
  • 이더넷이나 IP에도 같은 제어 정보가 있어 용어상 혼란을 야기할 수 있기에 TCP 헤더, IP 헤더, 이더넷 헤더와 같이 명확하게 써야한다.
  • 소켓에는 프로토콜 스택의 동작을 제어하기 위한 정보들이 수시로 기록된다.
    • 애플리케이션에서 통지된 정보
    • 통신 상대로부터 받은 정보
    • 송수신 동작의 진행 상황
  • 소켓의 제어 정보는 프로토콜 스택의 프로그램과 일체화 되어 있다고 볼 수 있다.
    통신 동작에 이용하는 제어 정보
-   헤더에 기입되는 정보
-   소켓(프로토콜 스택의 메모리 영역)에 기록되는 정보

접속 동작의 실제

  • 애플리케이션의 Socket의 connect를 호출하면, 서버 측 IP 주소와 포트 번호 명령이 프로토콜 스택 내부의 TCP로 전달된다.
  • TCP 담당 부분은 IP 주소로 표시된 상대측 서버의 TCP와 제어 정보를 주고받는다.
대화 과정 
1.  데이터 송수신 동작의 개시를 나타내는 제어 정보를 기록한 TCP 헤더를 만든다.
    - 송신처와 수신처의 포트 번호로 접속하는 소켓을 지정한다.
2.  TCP 헤더를 IP 담당 부분에 건네어 송신을 의뢰한다.
3.  IP 담당 부분이 패킷 송신을 실행하고 패킷이 서버에 도착하면 서버측 IP 담당 부분이 TCP 담당 부분에게 건넨다.
4.  서버측 TCP 담당 부분이 TCP 헤더를 조사하여 기록된 수신처 포트 번호에 해당하는 소켓을 찾는다.
5.  해당되는 소켓을 발견하면 필요한 정보를 기록하고 접속 동작을 진행중 상태로 변경한다.
6.  위 과정이 끝나면 서버의 TCP 담당 부분은 응답을 돌려보낸다.
  - 응답을 보낼 때 패킷을 받은 것을 알리기 위해 ACK 컨트롤 비트를 1로 만든다.

3. 데이터를 송수신한다

프로토콜 스택에 HTTP 리퀘스트 메시지를 넘긴다

  • connect에서 애플리케이션으로 제어가 되돌아오면 데이터 송수신 동작에 들어간다.
  • 데이터 송수신 동작은 애플리케이션이 write를 호출해 송신 데이터를 프로토콜 스택에 건네주는 것부터 시작된다.
  • 프로토콜 스택은 받은 데이터를 바로 송신하지 않고, 자체적으로 갖고 있는 송신용 버퍼 메모리 영역에 저장한다.
    • 바로 송신하지 않고 데이터를 임시 영역에 담는 이유는, 애플리케이션마다 데이터의 길이나 송신 방식이 다르기 때문이다.
  • MTU: 패킷 하나로 운반 가능한 데이터의 최대 길이
  • MSS: 헤더를 제외한 하나의 패킷으로 운반 가능한 TCP 데이터의 최대 길이
  • 만약 애플리케이션의 송신 속도가 느려지고, MSS에 가깝게 데이터를 저장해야 한다면 송신 동작이 지연이 생길 수 있다.
    • 따라서 버퍼에 데이터가 모이지 않아도 프로토콜 스택 내부의 타이머를 통해 일정 시간 이상을 경과할 때마다 송신이 가능하다.

ACK 번호를 사용하여 패킷이 도착했는지 확인한다

  • TCP에는 송신한 패킷이 상대방에게 제대로 도착했는지 확인하고, 도착하지 않았다면 재송신하는 기능이 있어 패킷을 송신하면 확인 동작을 한다.
  • TCP는 데이터 조각을 송신할 때 세어둔 값을 시퀀스 번호라는 항목으로 TCP 헤더에 기록한다.
  • 이를 통해 수신측에서 패킷에 누락이 있는지 확인이 가능하고, 누락이 없다면 TCP 헤더의 ACK 번호를 송신 측에게 알려준다.
  • 시퀀스와 ACK 번호로 패킷이 수신측에 올바르게 도착했는지 확인하는 것을 알 수 있다.

패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다

  • ACK 번호가 돌아오기를 기다리는 시간을 타임아웃 값이라고 한다.
  • 만약, 네트워크 혼잡으로 ACK 번호가 돌아오지 않으면서 타임아웃 시간이 지나면 재송신을 하게 되면 안그래도 혼잡한 네트워크에 부하를 더 악화시킬 수 있다.
  • 따라서 타임아웃 값은 다양한 요건을 고려해서 결정해야 한다.
  • TCP는 타임아웃 값을 ACK 번호가 돌아오는 시간을 기준으로 동적으로 변경한다.

윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다

  • ACK 번호가 돌아오기까지 아무 액션을 취하지 않는 것은 리소스 낭비이다.
  • 따라서 TCP는 윈도우 제어라는 방식에 따라 송신과 ACK 번호 통지 동작을 실행한다.
  • 윈도우 제어: 하나의 패킷을 보낸 후 ACK 번호를 기다리지 않고 패킷을 계속하여 보내는 방법이다.
    • ACK 번호가 돌아오기를 기다리지 않으므로 대기 시간을 낭비하지 않는다.
    • 하지만, ACK 번호를 기다리지 않고 패킷을 계속 보내면 수신측 능력을 초과하는 사태가 일어날 수 있다.
  • 수신측 TCP는 패킷 수신 시 일단 수신용 버퍼 메모리에 데이터를 일시적으로 보관하는데, 애플리케이션에서 데이터를 건네주는 처리가 끝나지 않았는데 다음 데이터가 들어오고 이를 반복하게 되면, overflow 현상이 되버린다.
  • 그래서 윈도우 제어는 이를 회피하기 위해 수신측에서 송신측에 수신 가능한 데이터 양을 통지하고, 이 양을 초과하지 않도록 송신을 한다.
    • 설명: 수신측에서 수신 처리가 끝나고 버퍼에 빈 부분이 생기면 그 분량만큼 수신 가능한 데이터 양을 늘리므로 TCP 헤더의 윈도우 필드에서 송신측에게 알린다.

ACK 번호와 윈도우를 합승한다

  • 송수신 동작에 있어 윈도우와 ACK 번호를 통지하게 되는데, 이를 각각 통지하면 송신하는 패킷이 불필요하게 많아져 효율성이 저하된다.
  • 따라서 수신측은 ACK 번호나 윈도우를 통지할 때 소켓을 바로 보내지 않고 잠시 기다린 후, 한 개의 패킷으로 묶어 보낸다.
  • 또한, ACK 번호 또는 윈도우가 연속하여 통지가 일어나는 상황에는 최후의 것만 통지하고 도중은 생략한다.

프로토콜 스택 데이터 수신 동작 간략 정리

  • 수신한 데이터 조각과 TCP 헤더 내용을 조사해 데이터 누락을 검사하고, 문제가 없으면 ACK 번호를 반송한다.
  • 데이터 조각을 수신 버퍼에 일시 보관하고, 조각을 연결해 데이터를 원래 모습으로 복원하여 애플리케이션에게 건네준다.
  • 애플리케이션에게 데이터를 건네주고 타이밍을 가늠해 윈도우를 송신측에 통지한다.

4. 서버에서 연결을 끊어 소켓을 말소한다

데이터 보내기를 완료했을 때 연결을 끊는다

  • 애플리케이션이 데이터를 전부 송신하면 연결 끊기 단계로 들어는데, 어디에서 송수신 동작이 끝나는지는 애플리케이션에 따라 다르다.
  • 서버
    • 서버측 애플리케이션이 Socket 라이브러리의 close를 호출한다.
    • 서버측 프로토콜 스택이 TCP 헤더에 FIN 1을 설정하고 IP 담당 부분에 의뢰하여 클라이언트에게 송신한다.
  • 클라이언트
    • 서버에서 FIN 1로 설정된 TCP 헤더가 도착하면 클라이트언트의 프로토콜 스택이 서버가 연결 끊기에 들어간 것을 알게 된다.
    • ACK 번호를 서버에 반송하고 애플리케이션이 데이터를 가지러 오길 기다린다.
    • 애플리케이션이 read로 데이터를 가지러 오면, 데이터를 건네지 않고 서버에서 보낸 데이터를 전부 수신 완료했다는 것을 클라이언트 애플리케이션에게 알린다.
    • 서버에서 보낸 데이터를 모두 수신했으니, 클라이언트도 close를 호출해 연결 끊기 동작으로 들어간다.
    • 클라이언트 프로토콜도 서버측과 마찬가지로 FIN에 1을 설정한 TCP 헤더를 만들고 서버에 송신, 서버에서 ACK 번호가 돌아오면 연결이 끝난다.

소켓을 말소한다

  • 연결을 끊고 소켓이 당장 필요 없지만, 소켓을 바로 말소하진 않고 오동작을 막기 위해 잠시 대기 후에 말소시킨다.

참고

책 정보

성공과 실패를 결정하는 1%의 네트워크 원리

목차

1장: 웹 브라우저가 메시지를 만든다
2장: TCP/IP의 데이터를 전기 신호로 만들어 보낸다
3장: 케이블의 앞은 LAN 기기였다
4장: 액세스 회선을 통해 인터넷의 내부로!
5장: 서버측의 LAN는 무엇이 있는가?
6장: 웹 서버에 도착하여 응답 데이터가 웹 브라우저로 돌아간다

댓글
링크
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday