TCP/IP 프로토콜은 연결이 생성된 이후 데이터 송수신이 시작된다.
이에 데이터가 확실히 전달되도록 보증하는 기능에 대해 알아보자.
데이터 손실을 방지하는 구조
이는 확인 응답과 재전송으로 구현된다.
수신 측에 TCP 세그먼트가 도착하면 수신 측은 송신 측에게 도착을 알린다.
이 때 반환하는 것을 ACK
라고 하며, TCP 헤더에 ACK 관련 정보를 넣은 TCP 세그먼트를 반환한다.
즉, 하나의 TCP 세그먼트로 응답할 때 데이터의 ACK를 동시에 반환하여 왕복 횟수를 줄인다.
송신 측은 ACK가 돌아오는 것을 보고 전송한 세그먼트가 무사히 도착했다는 것을 알 수 있다.
ACK가 오지 않으면 무슨 문제가 생긴것이므로 언제든지 재전송 할 수 있도록 전송이 끝난 TCP 세그먼트도 ACK를 받기 전까지는 소켓 버퍼에 남겨 둘 필요가 있다.
데이터 순서를 보증하는 구조
이는 각 TCP 세그먼트에 시퀀스 번호를 붙여 구현한다.
시퀀스 번호도 TCP 헤더에 기록되며, 해당 TCP 세그먼트가 전송 데이터 중 몇 바이트부저 시작하는지 가리키고 있다. 예를들어 3000바이트의 데이터를 보낼 때 1460, 1460, 80으로 분할한다.
이 때 첫 번째 세그먼트 시퀀스를 1, 두 번쨰를 1461, 세 번째를 2921로 한다.
수신 측은 이 시퀀스 번호를 사용해서 순서대로 조립한다.
(세그먼트 최대크기인 MSS는 보편적으로 1460byte이다.)
TCP 재전송 제어
이런 순차적 조합을 위해 수신 측은 ACK를 반환할 때 다음 필요한 TCP 세그먼트 시퀀스 번호도 ACK 번호로 전달한다. 예를 들어, 아프이 3000바이트에서 두 번째 세그먼트 수신이 완료된 경우, 다음 필요한 것은 세 번째 세그먼트 이기 때문에 다음 시퀀스 번호는 2291(2920까지 모두 도착했음)부터 보내라는 내용으로 응답한다.
ACK가 재전송되는 시점
- 일정 시간 내 ACK가 돌아오지 않으면 재전송한다.
- 순서대로 ACK가 오지 않은 경우 재전송하게 되는데, 이 때 ACK번호가 앞전과 같은 것이 3회 중복되어 도착할경우 이를 중복 ACK(Duplicate)라고 한다. 3번 기다리는 이유는 중간 세그먼트도 도착 순서가 바뀔수 있기 때문이다.
SACK: 상세한 ACK 반환 옵션
흐름 제어
동기로 통신하면 효율이 나빠 ACK를 기다리지 않고 전송하는 것이 좋다.
TCP는 어느 정도의 세그먼트 수라면 ACK를 기다리지 않고 전송하는 윈도우라고 하며 ACK없이 전송 가능한 데이터 크기를 윈도우 크기라고 한다.
윈도우에는 수신 측의 수신 윈도우와 송신 측의 폭주(송신) 윈도우, 두 가지가 있다. 기본적으로는 수신 측이 폭주 윈도우 크기를 조정해서 폭주 윈도우와 수신 윈도우 중 작은 쪽을 송신 윈도우로 채택하며, 이 범위 내에는 ACK를 기다리지 않고 전송한다.
ACK가 오면 해당 TCP 세그먼트는 재존성 할 필요가 없기 때문에 송신용 소켓 버퍼에서 삭제하고 송신 윈도우를 다음으로 이동한다. 이 과정을 슬라이딩 윈도우
라고 한다. 수신 측은 수신용 소켓 버퍼가 넘쳐서 수신이 불가능 하게 되면 수신 윈도우 크기를 작게 만들고 송신 측에 알린다.
송신 측은 수신 윈도우 크기 이상의 데이터는 ACK 없이 보낼 수 없게 된다. 이것이 TCP 흐름 제어(유량제어
)다.
이해한 내용을 정리하면 수신 측 소켓버퍼가 넘치기 전 까지는 ACK없이 계속 보낼 수 있다는 뜻 이다.
(송신 윈도우 크기란 수신측의 확인 응답 없이, 한 번에 전달 할 수 있는 바이트 사이즈를 말한다.)
폭주 제어
송신 측 윈도우를 폭주 윈도우라고 하는 이유는 이 송신 윈도우 크기는 네트워크 혼잡도에 맞추어 변경하기 때문이다.
(여기서는 폭주 윈도우라고 표현하지만 혼잡 윈도우라고 하기도 한다.)
네트워크가 혼잡해지면 폭주 윈도우 크기를 작게 해서 전송 데이터 양을 줄인다. 이것이 폭주 제어다. TCP는 주변에 영향을 주지 않도록 자중하는 프로토콜이다.
폭주 윈도우 크기는 통신 시작 시 1세그먼트에 설정된다.
수신 측 ACK 반환 시 마다 지수함수적으로 늘려나간다.
어느 정도 크기가 증가하면 그 이후는 1세그먼트씩 크기를 늘려나가다 실패하거나 혼잡을 감지하면 크기를 작게 해서 송신량을 줄인다. 그리고 다시 크기를 키우는 변화를 반복하며 주변에 피해 없이 전송속도를 최대로 조정할 수 있다.
송신 측은 받은 수신 윈도우 크기와 폭주 윈도우 크기 중 작은 쪽에 맞추어 전송량을 제어한다. 이 형식으로 흐름 제어 폭주 제어가 이루어진다.
'IT개념 > 프로그래밍상식' 카테고리의 다른 글
[DEVIEW2023] 런타임 데드 코드 분석 도구 Scavenger (0) | 2023.03.17 |
---|---|
인텔리제이 자주쓰는 단축키 (0) | 2022.01.07 |
캐시에 대하여 (0) | 2021.08.18 |
CORS, SameSite 이슈 (0) | 2021.08.05 |
프로그래밍을 배우기 어려운 이유와 극복하는 방법 (2) | 2021.06.07 |