TCP 3 way handshake & 4 way handshake
연결을 성립하고 해제하는 과정을 말한다.
TCP 는 연결 수립과 종료 과정에서 각각 3-way handshake 와 4-way handshake 라는 메커니즘을 사용한다.
보통 단어들에 대해서는 익숙하지만, 사실은 왜 그 횟수가 필요한지, 각 패킷이 어떤 역할을 하는지에 대해서 아는 것이 더 중요하다.
3 way handshake
TCP는 장치들 사이에 논리적인 접속을 성립시키기 위해 3 way handshake를 사용한다.
풀어서 말하자면, TCP/IP 프로토콜을 이용해서 통신을 하는 응용프로그램이 데이터를 전송하기 전에 먼저 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립하는 과정을 의미한다.
작동방식
-
SYN (Synchronize): 클라이언트가 서버에게 연결을 요청하며, 자신의 초기 시퀀스 번호
x를 전송한다. -
SYN-ACK: 서버가 클라이언트의 SYN 을 받았음을 확인(ACK=x+1)하고, 동시에 자신의 초기 시퀀스 번호
y를 포함한 SYN 을 전송한다. -
ACK: 클라이언트가 서버의 SYN 을 받았음을 확인한다.

왜 3번의 교환이 필요한가?
만약 3번의 교환을 하지 않는다고 생각해보면 문제가 명확하다.
-
시퀀스 번호는 전역 클록에 묶여있지 않다: 각 TCP 엔드포인트는 독립적으로 초기 시퀀스 번호(ISN)을 생성한다. 네트워크상에 전역 동기화 메커니즘이 없기 때문이다.
-
지연된 오래된 패킷 문제: 네트워크에서 지연된 이전 연결의 SYN 패킷이 새 연결 시도로 오해될 수 있다. 첫 번째 SYN 을 받은 쪽은 이것이 오래된 패킷인지 새로운 요청인지 알 수 없다.
-
송신자 검증 필요: 수신자는 반드시 송신자에게 “이거 님이 보낸거 맞음?” 을 확인해야한다.
양방향 동기화, 완전한 동기화를 위해서는:
-
각 측이 자신의 ISN 을 전송하고
-
상대방의 ISN 을 수신하고
-
각 ISN 에 대한 ACK 를 주고 받아야한다.
서로의 ACK 를 수신하는 것 까지 확인하기 위해서 3-Way 여야한다.
클라이언트 상태 전환:
CLOSED → SYN_SENT → ESTABLISHED
서버 상태 전환:
LISTEN → SYN_RECEIVED → ESTABLISHED
4 way handshake
4 way handshake는 연결을 해제하는 과정이다. 여기서는 FIN 플래그를 이용한다.
- FIN : 세션을 종료시키는데 사용되며, 더 이상 보낸 데이터가 없음을 나타낸다.
Termination의 종류
TCP는 두 가지 연결 해제 방식이 있다.
- Graceful connection release(정상적인 연결 해제)
정상적인 연결 해제에서는 양쪽이 커넥션을 모두 닫을 때까지 연결되어 있다.
-
Abrupt connection release(갑작스런 연결 해제)
-
갑자기 한 TCP 엔티티가 연결을 강제로 닫는 경우
-
한 사용자가 두 데이터 전송 방향을 모두 닫는 경우
-
Abrupt
RST(TCP reset) 세그먼트가 전송되면 갑작스러운 연결 해제가 수행되는데, RST 세그먼트는 다음과 같은 경우에 전송된다.
-
존재하지 않는 TCP 연결에 대해 비 SYN 세그먼트가 수신된 경우
-
열린 커넥션에서 일부 TCP 구현이 잘못된 헤더가 있는 세그먼트가 수신된 경우
- RST 세그먼트를 보내, 해당 커넥션을 닫아 공격을 방지한다.
-
일부 구현에서 기존 TCP 연결을 종료해야 하는 경우
Graceful
연결 종료 요청 역시, 요청을 먼저 시도한 요청자를 Client로, 요청을 받은 수신자를 Server 쪽으로 생각하면 된다.
-
클라이언트는 서버에게 연결을 종료한다는 FIN 플래그 보냄.
-
서버는 FIN을 받고, 확인했다는 ACK를 클라이언트에게 보낸다. 이 때, 모든 데이터를 보내기 위해 CLOSE_WAIT 상태가 된다.
-
데이터를 모두 보냈다면, 연결이 종료되었다는 FIN 플래그를 클라이언트에게 보낸다.
-
클라이언트는 FIN을 받고, 확인했다는 ACK를 서버에게 보낸다. 이 때 아직 서버로부터 받지 못한 데이터가 있을 수 있으므로 TIME_WAIT을 통해 기다린다.
-
서버는 ACK를 받고, 소켓을 닫는다(Closed)
-
TIME_WAIT 시간이 끝나면 클라이언트도 닫는다 (Closed) => 의도치 않은 에러로 연결이 데드락으로 빠지는 것을 방지한다.
-
이렇게 4번의 통신이 완료되면 연결이 해제된다.