TCP 유한 상태 머신
TCP 연결은 단순히 연결/해제가 아닌 약 11개의 세밀한 상태를 거친다.
-
3-Way-Handshake(연결 시작): LISTEN → SYN_SENT → SYN_RECV → ESTABLISHED 과정에서 각 플래그(SYN, ACK)가 어떻게 상태를 변화시키는지 분석한다.
-
4-Way-Handshake(연결 종료): 가장 사고가 많은 구간으로 FIN_WAIT_1, FIN_WAIT_2, TIME_WAIT 등의 상태 변화를 다룬다.
TIME_WAIT 그리고 CLOSE_WAIT
서버 운영 시 반드시 마주하게 되는 장애 포인트이다.
-
TIME_WAIT(정상 종료): 먼저 종료를 요청한 쪽에 남는 상태로 마지막 ACK가 유실되었을 경우를 대비하고, 네트워크에 떠도는 일명 미아 패킷이 다음 연결에 영향을 주지 않도록 대기한다.
- 문제: 단 시간에 많은 연결이 생성 및 종료되면 로컬 포트가 고갈되어 새로운 연결을 맺을 수 없게 된다.
-
CLOSE_WAIT(애플리케이션 버그 징후): 상대방이 종료를 요청했는데, 내 프로그램에서 Close(), Dispose() 등의 메소드를 호출하지 않을 때 발생한다.
- 위험성: 이 상태는 타임아웃이 없으므로 프로그램이 종료될 때까지 무한히 소켓을 점유하여 소켓 누수의 주범이 된다.
성능 최적화 Nagle 알고리즘과 NoDelay
데이터 전송 효울과 응답 속도 사이의 트레이드오프(Trade-Off)를 설정한다.
-
Nagle 알고리즘: 작은 패킷을 매번 보내는 대신, 모아서 한 번에 보내는 방식이다. 대역폭 효율은 좋지만 응답 속도(Latency)가 떨어진다.
-
C# 언어: 실시간 게임이나 채팅처럼 빠른 반응이 필요한 경우 Nagle 알고리즘을 끈다. 속성 Socket.NoDelay = true 설정으로 알고리즘을 끌 수 있다.
-
Linger 옵션: 소켓을 닫을 때 버퍼에 남은 데이터를 어떻게 처리할 지 결정하는 제어법을 다룬다.