TCP(Transmission Control Protocol)는 IP 위에서 연결 지향 · 신뢰성 있는 바이트 스트림을 제공하는 전송 계층 프로토콜이다. 순서 번호(sequence number)와 확인 응답(ACK)으로 손실을 재전송하고, 수신 윈도우와 혼잡 제어로 전송량을 조절한다. 현행 규격은 RFC 9293 이며 RFC 793 을 비롯한 7개 문서를 통합·대체했다[1].
세그먼트 헤더의 핵심 필드는 다음과 같다.
| 필드 | 크기 | 역할 |
|---|---|---|
| Source / Destination Port | 16비트 × 2 | 양 끝 애플리케이션 식별. (src IP, src port, dst IP, dst port) 4-tuple 이 연결 하나를 정한다 |
| Sequence Number | 32비트 | 이 세그먼트의 첫 바이트 번호. SYN·FIN 도 1바이트를 소비한다 |
| Acknowledgment Number | 32비트 | 다음에 받기를 기대하는 바이트 번호 (ACK 플래그가 켜졌을 때 유효) |
| Flags | 9비트 | SYN ACK FIN RST PSH URG + ECN 용 ECE CWR NS |
| Window | 16비트 | 수신 측이 더 받을 수 있는 바이트 수 (window scale 옵션으로 확장) |
| Options | 가변 | MSS · Window Scale · SACK · Timestamps 등 |

| 순서 | 방향 | 세그먼트 | 보내는 쪽 상태 → | 받는 쪽 상태 → |
|---|---|---|---|---|
| 1 | 클라이언트 → 서버 | SYN seq=x |
CLOSED → SYN-SENT | LISTEN → SYN-RECEIVED |
| 2 | 서버 → 클라이언트 | SYN+ACK seq=y, ack=x+1 |
SYN-RECEIVED | SYN-SENT → ESTABLISHED |
| 3 | 클라이언트 → 서버 | ACK seq=x+1, ack=y+1 |
ESTABLISHED | SYN-RECEIVED → ESTABLISHED |
초기 순서 번호(ISN)는 양쪽이 각각 무작위로 고르며, SYN 이 1바이트를 소비하므로 상대는 ISN+1 로 ACK 한다. 서버는 3번 ACK 를 받아야 ESTABLISHED 가 되고, 그전까지의 반쯤 열린 연결이 SYN backlog 에 쌓인다.
양쪽이 각각 자기 방향을 닫는다(half-close). 먼저 닫는 쪽을 능동(active), 나중에 닫는 쪽을 수동(passive) 종료라고 한다.
| 순서 | 방향 | 세그먼트 | 능동 종료 측 | 수동 종료 측 |
|---|---|---|---|---|
| 1 | A → B | FIN |
ESTABLISHED → FIN-WAIT-1 | ESTABLISHED |
| 2 | B → A | ACK |
FIN-WAIT-1 → FIN-WAIT-2 | → CLOSE-WAIT |
| 3 | B → A | FIN |
FIN-WAIT-2 | CLOSE-WAIT → LAST-ACK |
| 4 | A → B | ACK |
FIN-WAIT-2 → TIME-WAIT → (2MSL 후) CLOSED | LAST-ACK → CLOSED |
2와 3이 한 세그먼트(FIN+ACK)로 합쳐지기도 한다. 양쪽이 동시에 FIN 을 보내면 CLOSING 상태를 거친다.
TIME-WAIT 는 마지막 ACK 가 유실됐을 때 상대의 FIN 재전송에 답하고, 같은 4-tuple 의 옛 세그먼트가 새 연결에 섞이지 않게 하려고 2×MSL(Maximum Segment Lifetime) 동안 머무는 상태다. 능동 종료 측에만 생기므로, 서버가 연결을 먼저 끊는 구조에서는 서버에 TIME-WAIT 가 쌓인다.
RFC 9293 3.3.2 절이 정의하는 11개 상태다[1:1].
| 상태 | 의미 |
|---|---|
| LISTEN | 원격의 연결 요청을 기다림 (서버 소켓) |
| SYN-SENT | SYN 을 보내고 응답을 기다림 |
| SYN-RECEIVED | SYN 을 받고 SYN+ACK 를 보낸 뒤 ACK 를 기다림 |
| ESTABLISHED | 연결 완료. 데이터 전송 가능 |
| FIN-WAIT-1 | FIN 을 보내고 그 ACK(또는 상대 FIN)를 기다림 |
| FIN-WAIT-2 | 내 FIN 은 확인됐고 상대 FIN 을 기다림 |
| CLOSE-WAIT | 상대 FIN 을 받았고 로컬 애플리케이션이 close() 하기를 기다림 |
| CLOSING | 양쪽이 동시에 FIN 을 보낸 뒤 ACK 를 기다림 |
| LAST-ACK | 내 FIN 에 대한 ACK 를 기다림 |
| TIME-WAIT | 2MSL 대기 |
| CLOSED | 연결 없음 (가상의 상태) |
운영 관점에서 눈여겨볼 상태는 다음과 같다.
# 상태별 소켓 수
ss -tan state established | wc -l
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn
# 특정 포트의 연결
ss -tanp '( sport = :443 )'
# 소켓 통계 요약
ss -s
# 리스닝 소켓
ss -tlnp
netstat 은 net-tools 소속으로 최근 배포판에서는 기본 설치되지 않는다. ss(iproute2)가 같은 정보를 더 빠르게 보여 준다.
/proc/sys/net/ipv4/ 아래 값이며 sysctl 로 읽고 쓴다. 기본값 설명은 커널 문서 기준이다[2].
| 파라미터 | 기본값 | 의미 |
|---|---|---|
net.ipv4.tcp_fin_timeout |
60 | 애플리케이션이 놓아 버린(orphan) 소켓이 FIN-WAIT-2 에 머무는 최대 초. TIME-WAIT 길이가 아니다 |
net.ipv4.tcp_tw_reuse |
2 | TIME-WAIT 소켓을 새 outgoing 연결에 재사용. 0 끔 · 1 전체 · 2 루프백만 |
net.ipv4.tcp_max_syn_backlog |
메모리 비례 | 리스너당 SYN-RECEIVED 로 기억할 최대 요청 수 |
net.ipv4.tcp_syncookies |
1 | SYN backlog 가 넘칠 때 syncookie 로 응답. SYN flood 완화용이며 TCP 옵션 일부를 잃는다 |
net.ipv4.ip_local_port_range |
32768 60999 | 능동 연결에 쓰는 임시 포트 범위. TIME-WAIT 로 포트가 마를 때 넓힌다 |
net.core.somaxconn |
4096 | listen() backlog 의 상한 (완료된 연결 큐) |
tcp_tw_recycle 은 커널 4.12 에서 제거됐다. NAT 뒤의 클라이언트를 끊는 부작용 때문이며, 옛 튜닝 가이드에 남아 있어도 넣지 않는다.
# 확인
sysctl net.ipv4.tcp_fin_timeout net.ipv4.tcp_tw_reuse net.core.somaxconn
# 영구 적용
cat <<'EOF' > /etc/sysctl.d/90-tcp.conf
net.ipv4.ip_local_port_range = 10240 65000
net.core.somaxconn = 8192
EOF
sysctl --system
RFC 9293 "Transmission Control Protocol (TCP)" (STD 7, 2022-08). RFC 793 · 879 · 2873 · 6093 · 6429 · 6528 · 6691 을 대체 — 2026-09-20 확인. https://www.rfc-editor.org/rfc/rfc9293.html ↩︎ ↩︎
Linux kernel Documentation/networking/ip-sysctl.txt — 2026-09-20 확인. https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt ↩︎