Skip to main content

TCP

TCP(Transmission Control Protocol)란, 두 네트워크 호스트간 전송하는 패킷의 순서를 보장하는 전송제어 프로토콜이다. 주로 IP와 함께 사용되어, TCP/IP 프로토콜로 두 네트워크 호스트의 통신을 담당한다.

TCP는 1:1로 통신하는데, 연결을 수립할 때는 3-way handshake로, 해제할 때는 4-way handshake로 해제한다.

또한, TCP는 여러 프로토콜의 기반이 되기도 하는데, 가령 TCP 기반의 HTTPS 프로토콜의 경우 TCP의 3-way handshake로 연결을 수립한 다음, HTTPS의 SSL handshake가 이루어진다.


TCP Segments

TCP 세션으로 연결된 양 끝단 간에 서로 교환 및 전달되는 데이터 단위이다. TCP Header와 Packet(Data)으로 구성된다. (참고로 UDP의 경우, UDP Segment가 아닌, UDP Datagram이라 표현한다)

TCP Header

RFC 9293에서 다음과 같이 TCP Header의 구조를 보여주고 있다.

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |C|E|U|A|P|R|S|F| |
| Offset| Rsrvd |W|C|R|C|S|S|Y|I| Window |
| | |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| [Options] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :
: Data :
: |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

위 그림에서 한 tick은 1 bit를 의미한다. 따라서 다음과 같이 구성됨을 알 수 있다.

  • Source Port: 16 bits
  • Destination Port: 16 bits
  • Seqeunce Number: 32 bits
  • Acknowledgment Number: 32 bits
  • Data Offset(a.k.a. DOffset): 4 bits
  • Control Bits(a.k.a. flags): 8 bits
  • Window: 16 bits
  • Checksum: 16 bits
  • Urgent Pointer: 16 bits
  • Options: size(Options) == (DOffset-5)*32 bits
    • DOffset 값이 5보다 클 경우에만 존재한다.
  • Data: 데이터 크기에 따라 가변적이다.

3-way handshake / 4-way handshake

단말기(End-point 또는 Host) 사이에서 다음과 같이 연결을 수립하고 해제한다.

이를 자세히 살펴보면 연결 수립과정은 다음과 같다.

info

참고로 연결 수립은 어느 쪽에서 먼저 요청해도 되지만, Client에서 Server로 연결 수립을 요청한다고 가정한다.

    TCP Peer A                                           TCP Peer B

1. CLOSED LISTEN

2. SYN-SENT --> <SEQ=100><CTL=SYN> --> SYN-RECEIVED

3. ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED

4. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK> --> ESTABLISHED

5. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED

Sequence Number(seq)는 임의로 생성한 난수로, Client에서 SYN flag와 함께 전송한다. 그리고 Client는 SYN-SENT 상태가 된다.

Server가 패킷을 받고 나면, 전달받은 seq 값에 +1한 값을 Acknowledgment Number(ack)로 만든다. 그리고 Server 또한 임의의 난수(seq)를 만들고 이를 SYN, ACK flag, ack 응답값 모두를 Client에 전송한다. 그리고 서버는 SYN-RECEIVED 상태가 된다.

마찬가지로 Client 또한 Server로부터 전달받은 seq 값에 +1한 값을 ack 응답값으로 해 Server에 전달한다. 그리고 Client는 ESTABLISHED 상태가 된다.

Server에서 ack 값을 받으면 마찬가지로 ESTABLISHED 상태가 된다.


연결 해제 과정을 자세히 보면 다음과 같다.

info

참고로 연결 해제 또한 어느 쪽에서 먼저 요청해도 되지만, Client에서 Server로 연결 해제를 요청한다고 가정한다.

    TCP Peer A (Client)                          TCP Peer B (Server)

1. ESTABLISHED ESTABLISHED

2. (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT

3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK> <-- CLOSE-WAIT

4. (Close)
TIME-WAIT <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK

5. TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> CLOSED

6. (2 MSL)
CLOSED

Client가 연결을 종료하기위해 FIN flag와 함께 seq 값을 보낸다. 그리고 Client는 FIN-WAIT-1 상태가 된다.

Server는 seq값에 +1한 값을 ack값으로 해서 ACK flag와 함께 Client에 전달한다. 그리고 CLOSE-WAIT 상태가 된다.

이때, Client는 FIN-WAIT-2 상태가 되며 여전히 Server로부터 FIN flag를 기다리고 있다.

Server는 seq를 생성해서 Client에 전달한다. 그리고 LAST-ACK 상태가 된다.

Client는 서버로부터 받은 seq 값에 +1한 값을 ack값으로 해서, ACK flag와 함께 전달한다. 그리고 TIME-WAIT 상태가 된다. 이때 TIME-WAIT 은, 먼저 연결을 종료하는 쪽에 생성되는 소켓으로 혹시 모를 패킷 전송 실패에 대비하기 위해 존재한다.

Server는 Client로부터 ack를 받은 다음, CLOSED 상태가 된다.

Client는 Server의 최대 세그먼트 수명(MSL)의 2배를 기다린 다음, CLOSED 상태로 바뀌며 연결이 종료된다.


몇 가지 궁금증

왜 무작위 Sequence Number를 보낼까?

Connection에 사용되는 포트는 유한하고, 시간이 지나면 재사용 된다. 그래서 이전에 사용된 포트번호를 사용할 가능성이 있기 때문에 무작위 숫자를 사용한다.


만약 FIN flag를 전송하기 전에 전송한 패킷이, Routing 지연이나 패킷 유실로 인한 재전송 등으로 인해 FIN 패킷보다 늦게 도착하는 상황이 발생하면 어떻게 될까?

이러한 현상에 대비해, FIN flag를 수신하더라도 일정시간(Windows의 경우, default로 240 seconds(4 min)를 기다린다.)동안 세션을 남겨 놓고 잉여 패킷을 기다리는 과정을 거친다. (TIME-WAIT 과정)


TCP에서는 어떻게 UDP와 달리, 3단계 연결 설정과 3/4단계 연결 종료를 할 수 있을까?

TCP는 버퍼링(Buffering) 방식 때문에 가능하다. TCP는 송수신자 사이에 연결 설정/종료 같은 상호작용이 가능하기 때문이다. 그래서 안정적인 전송을 요구하는 환경에서 사용한다.

반면에 UDP는 버퍼링 방식이 없어서 일방적인 전송만 가능하다. 그래서 UDP는 시간에 민감한 환경에서 사용한다.

Related Links