TCP; Transmission Control Protocol
TCP는 현재 중요하게 여겨지는 통신 규약 중 하나로 데이터를 안전하게 전달해주는 역할을 한다.
OSI 계층에서 Transport Layer 전송 계층에 해당되어 데이터를 전송한다.
계층 구조를 간단하게 설명한 위 글에서 전송 계층에서 TCP, UDP의 사용에 대한 차이를 적어보았다.
거기에 나와있는 흐름제어, 시퀀스 번호, 세그먼트 등‥ 자세하게 알아보기로 한다.
✔️ 세그먼트(Segment)로 전달한다?
4계층 구조에서 간단하게 설명할 때 '보장된 세그먼트'로 전달한다고 했다.
세그먼트는 TCP가 데이터를 나누는 단위로, TCP는 전송할 데이터를 세그먼트 단위로 나누어서 관리한다.
1️⃣ TCP 세그먼트
간단하게 말해서 세그먼트는 그냥 TCP가 전송하기 위한 데이터를 부르는 말이라고 생각할 수 있다.
세그먼트 단위로 나눈다는 건 특정 크기에 맞게 데이터를 분리한다는 것이고, 각 세그먼트(= 데이터)를 전송한다.
데이터 통째로 전송하는 것이 아니라 크기 별로 나누어서 관리하고 전송하는 것이다.
데이터는 저마다 헤더를 가지고 있는데, TCP가 데이터를 전송할 때 헤더에 세그먼트에 대한 내용을 같이 작성한다.
그 TCP헤더를 통해서 TCP세그먼트를 관리할 수 있는 것이다.
2️⃣ MSS; Maximum Segment Size
세그먼트로 전송할 수 있는 최대 데이터 크기를 MSS라고 한다.
결국 그 전송도 링크계층이 담당하기 때문에 MSS도 링크계층에 의존한다.
링크계층에서 전송하는 데이터 크기보다 큰 세그먼트는 전송하지 못한다. MSS도 그보다 클 수 없다.

만약 2500byte의 데이터가 전송되어야 할 때 MSS가 950으로 설정되어 있으면 TCP는 그 데이터를 950byte 크기를 최대치로 세그먼트로 나눌 수 있다. MSS보다 큰 크기의 세그먼트는 만들 수 없다.
3️⃣ Sequence Number
헤더에 포함되는 정보 중 순서 제어를 위해서 필요한 것이 이 시퀀스 넘버이다.
물리적으로 누군가에게 물건을 하나씩 전달할 때, 우리는 '직접' 전달하니 그 순서를 제어할 수 있다.
하지만 네트워크 망을 통해서 데이터를 전송하다보면 도중에 데이터가 사라지거나, 늦게 도착하여 순서가 뒤죽박죽이 되는 경우가 생긴다. 그 순서를 제어하기 위해 사용하는 것이 Sequence Number

시퀀스 넘버는 해당 세그먼트의 시작 데이터를 의미한다.
세그먼트가 시작하는 바이트가 몇번째 바이트인지 그 숫자를 사용한다.
위에서 분류한 세 세그먼트의 각 헤더에 저장된 시퀀스 넘버는 그림과 같다.
첫번째 세그먼트는 1byte부터 시작하고, 그 세그먼트의 크기는 950byte로 해당 세그먼트는 1byte~950byte까지 가지고 있다.
두번째 세그먼트는 바로 이어지는 951byte부터 시작해서 950byte를 가지고 있어 1900byte까지 포함한다.
마지막 세번째 세그먼트는 1901byte부터 시작해 2500byte까지 포함한다.
이렇게 헤더에 저장되는 시퀀스 넘버는 각 세그먼트에 있는 데이터의 첫번째 바이트 번호를 의미한다.
✔️ 포트 번호를 이용
상대 서버에 도착했지만, 우리가 전송한 이 데이터를 어떤 프로세스에 적용시켜야할지 결정하기 위해 포트번호를 이용한다.
만약 이 데이터를 80번 포트로 보냈다면 HTTP로 전달되고, 25번 포트로 전송했으면 SMTP에 사용된다.
포트는 0부터 65535번까지 존재하며, 이미 사용중인 포트번호도 있기 때문에 아무거나 사용하면 안 된다.
포트 번호에 대한 자세한 표는 인터넷을 통해 잘 알아보고 사용하자. → https://www.dsun.kr/77
✔️ 가상 경로를 생성해 논리적으로 연결
경로를 결정하는 것이 아닌 경로를 생성해서 연결할 수 있냐고 묻는 역할을 한다.
좀 더 나은 경로를 결정하는 건 L3 라우터 기능이다. 여기서 말하는 가상 경로 생성은 통신 상대와 연결하는 것
1️⃣ Port Listen, Established
TCP는 통신 상대에게 '지정 포트로 통신을 하겠다'는 요청을 보낸다.
상대방이 '통신을 해도 된다. OK'라는 응답을 보내면 가상 경로를 생성한다.
송신을 받는 쪽은 '지정 포트로 통신을 해도 된다'고 응답을 보낸 상태이기 때문에 통신이 오는 걸 기다린다.
그리고 통신 연결이 오면 그 연결을 받는다.
이렇게 통신을 하기 위해 기다리고 있는 대기 상태를 Listen
하고 있다고 한다.
연결에 성공하면 Established
상태로 변한다.
2️⃣ 3 Way HandShake
경로를 열어달라고 요청을 보내고, 그 요청을 받아 열어도 된다고 응답한 뒤, 확인했다는 응답을 보낸다.
연결을 위해서 요청과 응답이 3번 왔다갔다 하는 이 과정을 3 Way HandShake라고 한다.

SYN를 보내 연결을 요청하면서 시퀀스 번호를 같이 보낸다.
ACK로 요청에 응답을 해주며, 시퀀스 번호에 1을 더해서 보낸다.
서로 연결이 되어야 통신이 가능한 상태가 된다.
이렇게 3 Way HandShake 과정을 통해 두 소켓이 서로 연결되면 전용 회선이 있는 것처럼 통신한다.
가상 회로를 통해 논리적으로 연결되어 있다고 가정하고 통신하는 것이다.
✔️ 데이터 보증
TCP의 가장 중요한 역할이었던 데이터를 제대로 전달하는 방법은 아래와 같다.
1️⃣ 손실을 방지하기 위해 세그먼트 보관
데이터가 도착하면 수신측은 송신측에게 도착 응답 ACK를 보낸다.
데이터가 도착하지 않으면 응답 ACK를 보내지 않을 것이다.
데이터를 보내고 난 뒤에도 ACK가 도착하지 않으면, 데이터가 제대로 전송되지 않았을 경우를 생각해 데이터를 다시 전송해야 한다.
전송하고 나서 그 데이터를 바로 삭제해버리면 재전송할 수 없게 된다.
그래서 TCP는 세그먼트를 전송하고 나서도 소켓 버퍼에 남겨두고 보관한다.
데이터가 잘 도착했다는 응답ACK가 도착하면 정상적으로 전달한 세그먼트를 삭제한다.
2️⃣ 순서를 보증하기 위한 Acknowledgment Number 사용
데이터를 전달할 때 중간에 사라지기도 하고, 다른 세그먼트보다 늦게 도착하여 순서가 뒤죽박죽이 될 수도 있다.
데이터 순서를 제대로 맞춰주는 역할도 TCP에서 관리한다.
데이터가 제대로 도착하기 위한 모든 일은 TCP에서 관리한다고 생각하면 된다.
세그먼트마다 헤더에 Seqeunce Number를 지정해준다.
그렇게 순서를 맞춰주고, 송신측에서도 다음 순서의 데이터를 전달해달라고 요청하기 위해 번호를 지정한다.
그게 응답 확인 번호 Acknowledgment Number를 이용하는 것이다.
송신측에서는 '이 세그먼트를 보낸다!'하는 SEQ를 전달하고, 수신측에서는 '다음 데이터를 보내줘!'하는 ACK를 전달한다.

3️⃣ 데이터가 제대로 전송되지 않았을 때 재전송 제어
데이터가 제대로 전송되지 않았을 때, TCP는 다시 전송을 해야 한다.
재전송을 해야 하는 상황을 구분하는 방법은 세 가지가 있다.
1. Time Out
일정 시간 안에 잘 도착했다는 ACK가 오지 않을 경우
2. 중복 ACK
동일한 ACK가 일정 횟수 이상 오는 경우.
세그먼트마다 전달되는 속도는 동일하지 않을 수 있다. 좀 더 늦게 도착할 수 있기 때문에 같은 시퀀스 번호를 요청하는 ACK가 두번 왔다고 해서 바로 재전송하지 않는다. 일정 횟수 이상 중복 ACK가 발생하면 재전송한다.
3. Selective ACK (SACK)
상세한 정보를 담아서 ACK를 전달할 수 있다.
✔️ 흐름 제어 (유량 제어)
TCP는 데이터를 제대로 전달하는 역할도 하지만, 그 전송을 제어하는 역할도 함께 한다.
바로 위에서 다음 세그먼트를 달라고 요청하는 이미지 설명에 '잘 받았다는 SEQ와 함께 응답'한다고 적었다.
다음 세그먼트 번호도 요청하지만, 그 전에 보낸 데이터를 잘 받았다는 응답도 함께 보낸다.
하지만 잘 보면 송신측은 수신측에서 응답이 오기 전에 이미 다음 데이터를 전달하고 있다.
TCP는 비동기 통신을 지원해서 ACK를 기다리지 않고, 다음 세그먼트를 전송한다.
이렇게 ACK를 기다리지 않고 전송하는 것은 윈도우(Window)라고 한다.
1️⃣ 윈도우 크기
ACK를 받지 않고 전송할 데이터의 양을 지정할 수 있다. → 윈도우 크기 지정
윈도우 크기는 수신측에서 지정한다.
송신 윈도우와 수신 윈도우 크기를 비교해 더 작은 것을 송신 윈도우 크기로 채택한다.
그 범위 안에서 ACK를 기다리지 않고 전송할 수 있다.
2️⃣ 슬라이딩 윈도우
ACK가 오면 송신용 소켓 버퍼에서 삭제하고 송신 윈도우를 이동한다.
이렇게 윈도우를 이동하는 과정을 슬라이딩 윈도우라고 한다.
3️⃣ ACK를 받지 않고 전송하면 데이터 공간이 부족하지 않을까?
수신측은 수신용 소켓 범퍼가 넘치면, 수신 윈도우 크기를 작게 만든다.
윈도우 크기는 수신측에서 결정하고, 더 작은 것을 송신 윈도우 크기로 결정한다.
수신 측이 윈도우 크기를 작게 줄이면서, 한번에 받을 수 있는 데이터의 양을 줄이려고 한다.
수신 윈도우 크기를 줄였다는 내용을 송신측에 보내면 송신측은 그에 맞게 윈도우 크기를 줄여서 전송한다.
송신 측은 윈도우 크기 이상의 데이터는 ACK없이 보낼 수 없다.
윈도우 크기를 벗어나면 수신 측으로부터 ACK를 받아야 다음 데이터를 보낼 수 있다.
이렇게 윈도우를 사용하고 그 크기를 상황에 맞게 변동하며 흐름을 제어할 수 있게 된다.
4️⃣ 송신측은 윈도우 크기를 변경하지 못할까?
통신을 시작하면 윈도우 크기는 1세그먼트에 맞춰서 설정한다.
그리고 ACK가 도착하면 지수 함수적으로 윈도우 크기를 증가시킨다. → 2세그먼트, 4세그먼트, …
처음에는 1세그먼트 크기의 작은 윈도우로 시작했지만 점점 윈도우 크기가 커지게 되면서 혼잡 상태에 빠지게 된다.
이를 네트워크 폭주라고 하며, 폭주를 감지하면 송신측이 윈도우 크기를 변경한다.
윈도우 크기를 줄여서 송신량을 감소하고, 괜찮아지면 다시 천천히 증가시킨다.
이렇게 네트워크가 혼잡한 상황에 빠졌을 때 송신측이 윈도우 크기를 변경하는 것을 폭주 제어 라고 한다.
'ComputerScience > 네트워크' 카테고리의 다른 글
[Network] WAS(Web Application Server) 간단히 알아보기 (1) | 2025.02.05 |
---|---|
[Network] IP와 Routing에 대해 간단하게 알아보기 (0) | 2025.02.04 |
[Network] TCP/IP의 4계층 구조 알아보기 (0) | 2025.02.03 |