본문 바로가기
웹 개발

TCP에 대해 알아보자 (+Wireshark로 확인)

by xosoy 2025. 8. 16.
 

TCP (Transmission Control Protocol)

TCP는 연결 지향형 프로토콜로, 데이터 전송 전후에 Handshake 과정을 거쳐 연결을 수립하고 종료한다.

또한 데이터 전송의 신뢰성과 순서 보장을 위해 흐름 제어, 오류 제어, 혼잡 제어와 같은 기법을 사용한다.


1. 통신 과정

1.1 연결 수립 — 3-Way Handshake

클라이언트와 서버가 연결을 맺는 과정


1 클라이언트 → 서버: SYN 전송 (연결 요청) 클라이언트 → SYN_SENT
2 서버 → 클라이언트: SYN + ACK 전송 (요청 수락) 서버 → SYN_RCVD
3 클라이언트 → 서버: ACK 전송 (응답) 클라이언트·서버 → ESTABLISHED

결과: 양쪽 모두 ESTABLISHED 상태가 되어 데이터 송수신 가능.


1.2 데이터 전송

연결이 수립된 이후, 데이터를 주고받는 과정

  1. 송신 측이 데이터를 전송
  2. 수신 측은 정상 수신 시 ACK 전송
  3. 송신 측이 ACK를 받지 못하면 재전송 수행

1.3 연결 종료 — 4-Way Handshake

연결을 끊는 과정


1 클라이언트 → 서버: FIN 전송 (종료 요청) 클라이언트 → FIN_WAIT1
2 서버 → 클라이언트: ACK 전송 서버 → CLOSE_WAIT, 클라이언트 → FIN_WAIT2
3 서버가 남은 데이터 전송 후 FIN 전송 서버 → LAST_ACK
4 클라이언트 → 서버: ACK 전송 클라이언트 → TIME_WAIT
5 일정 시간 대기 후 클라이언트 CLOSED, 서버는 ACK 수신 시 CLOSED  

2. TCP의 제어 기법

2.1 흐름 제어 (Flow Control)

수신자의 처리 속도를 고려해 송신 속도를 조절

  • 슬라이딩 윈도우 방식
    • 데이터 저장 공간인 윈도우 크기를 조절하여 송신 가능한 데이터 양을 제한.

2.2 오류 제어 (Error Control)

전송 도중 데이터 유실·오류 발생 시 복구

  • Go-Back-N
    • 오류가 발생한 시점부터 이후 모든 데이터를 재전송.
    • 예: 1~5번 전송 중 4번 오류 → 4, 5번 다시 전송.
  • Selective Repeat
    • 오류가 발생한 데이터만 재전송.
    • 예: 1~5번 전송 중 4번 오류 → 4번만 재전송, 이후 6번부터 이어서 전송.

2.3 혼잡 제어 (Congestion Control)

네트워크 상태가 불안정할 때 전송량을 조절하여 네트워크 과부하를 방지


3. Wireshark로 확인해보기

Wireshark는 패킷을 실시간으로 캡처하고, 각 패킷의 세부 내용을 분석할 수 있는 네트워크 프로토콜 분석 도구이다. Wireshark를 이용해 TCP 연결 과정과 종료 과정을 실제 패킷 캡처를 통해 살펴보았다.

 

curl -v http://example.com/ 요청을 보내고 어떤 패킷이 오고가는지 확인해보자.
다음은 Wireshark에서 ip 주소를 가지고 필터링한 결과이다.

3.1 DNS 조회

  • [76] 클라이언트 → DNS 서버: example.com A 레코드 요청(IPv4)
  • [77] 클라이언트 → DNS 서버: example.com AAAA 레코드 요청(Ipv6)
  • [78] DNS 서버 → 클라이언트: IPv6 주소 응답
  • [79] DNS 서버 → 클라이언트: IPv4 주소 응답 (23.192.228.80)

3.2 TCP 3-way handshake (연결 성립)

  • [80] 클라이언트 → 서버: SYN (연결 요청)
  • [81] 서버 → 클라이언트: SYN, ACK (연결 수락)
  • [82] 클라이언트 → 서버: ACK (최종 확인 → 연결 성립)

3.3 HTTP 요청/응답

  • [83] 클라이언트 → 서버: HTTP GET 요청 (HTTP/1.1)
  • [91] 서버 → 클라이언트: HTTP 응답 (200 OK)

3.4 TCP 4-way handshake (연결 종료)

  • [92] 클라이언트 → 서버: ACK (데이터 확인)
  • [93] 클라이언트 → 서버: FIN, ACK (클라이언트 송신 종료)
  • [97] 서버 → 클라이언트: FIN, ACK (서버 송신 종료 + 클라이언트 FIN 수신 확인)
  • [98] 클라이언트 → 서버: ACK (서버 FIN 수신 확인 → 연결 종료)

Ack, Seq의 의미?

Seq(Sequence Number)는 보내는 데이터의 순서 번호이다. 각 TCP 세그먼트의 시작, 즉 첫번째 바이트 번호를 의미한다. 받은 마지막 바이트 순서 번호에 1을 더한 값이 된다.

 

Ack(Acknowledgement Number)는 상대가 보내주길 기대하는 다음 바이트 번호를 의미한다. 즉 받은 마지막 바이트 순서 번호에 1을 더한 값이 된다.

 

결과를 다시 살펴보자.

클라이언트가 HTTP 요청을 보내고 나니 Ack=75가 되었다.


요청을 확인해보니 길이가 74이다. 따라서 서버가 기대하는 다음 바이트 번호는 75가 되므로, Ack=75가 된다.

 

이후 서버가 보낸 ACK 패킷에는 Seq=1로 변함이 없다. 

 

그럼 언제 Seq가 증가하는거지?

확인해보니 데이터 전송(HTTP 요청/응답), SYN/FIN에 의해서만 증가한다. ACK는 Seq에 영향을 주지 않는다!

 

그리고 클라이언트와 서버는 독립적인 Seq 번호를 유지한다. (이 부분이 참 헷갈렸다...)

클라이언트만 따로 보자.

  1. SYN을 보내고 Seq가 0 → 1 로 증가한다.
  2. HTTP 요청(74바이트)를 보내고 Seq가 1 → 75로 증가한다.
  3. FIN을 보내고 Seq가 75 → 76로 증가한다.

즉, 각각 자신의 Seq를 따로 증가시키고, Ack는 상대의 Seq에 맞춰 증가한다.