본문 바로가기
CS/네트워크

[네트워크] 전송 계층 - TCP : segment 구조

by DenverAlmighty 2025. 1. 12.

5. 연결 지향 전송 : TCP

 

1) TCP 특징

  • point-to point : 한 전송측에서 한 수신측으로 전송
  • 신뢰성있는, 순차 바이트 스트림(in-order byte stream): 순서대로 전송. 어플리케이션 측에서 보면 하나의 스트림이 바이트 단위로 쭉 들어오는 것처럼 보인다. message boundaries가 없다. 데이터는 순서대로 application layer로 넘겨지며, 데이터를 byte로 처리하기 때문에 application message의 맥락을 신경쓰지 않는다.
  • 파이프라인(Pipelined) : 데이터를 버퍼에 받아서 저장, 흐름, 혼잡 제어가 window 크기를 설정한다.
  • 연결 지향 : 통신을 하기 앞서 Handshaking 과정을 통해 sender와 receiver의 상태를 확인한다.
  • 흐름 제어 : 발신측이 수신측의 속도를 넘지 않는다.
  • 전이중(full duplex) 데이터 전송:
    • 동일한 연결에서 양방향으로 데이터가  흐른다.
    • MSS: 최대 세그먼트 크기

 

 

2) TCP 세그먼트 구조

1) 

헤더는 상대방과 협력하기 위한 정보가 담긴 것인데, TCP는 UDP보다 많은 기능을 지원하므로 헤더에 더 많은 요소가 들어간다. 

TCP 헤더 길이는 가변적이므로 Header len필드가 있다. (UDP는 헤더 길이 고정, 세그먼트 전체 길이 알려주는 len 필드 있었음)

 

2) TCP의 헤더

TCP의 고정 헤더는 32bit(=4bit) * 5 로 TCP헤더의 최소 길이는 20 byte이다.

1) source port 2) dest port
3) sequence number
4) ack number
5) header len | not used | U | A | P | R | S | F 6) receive window
7) checksum 8) Urg data pointer
 9) Options (길이 가변)
10) Application data
(길이 가변)

 

  • 3) Sequence Number :
    TCP는 연결 설정(connection setup) 시 몇번째 바이트부터 전송할 지 결정한다.
    TCP는 application data에 포함된 데이터의 첫 바이트가 몇번째 인지 표시한다.
    이번 segment에 실린  데이터의 user data의 첫번째 바이트가 sequence number의 몇번째 바이트인지 알려준다. 
  • 4) ack number :
    상대방이 나에게 보낸 데이터에 대한 ack number이다. "(ack number -1) 까진 잘 받았어, 다음엔 ack number 보내줘"
  • 5)
    • header len : 헤더 길이
    • not used :
    • flag bit
      • U(URG) : Urgent data. U flag가 있는 경우, P와 동일하게 동작하는데, 차이점은 U에 Ugent 데이터가 어디인지 표시한다. 수신측에서도 마찬가지이다. (일반적으로 사용 안한다.)
      • A(ACK) : ack 할 게 없는 상황에서는 0으로 표시하고, ack number에 값은 의미가 없다.
      • P(PSH) : TCP에서는 데이터를 받으면 버퍼에 저장 후, 혼잡, 흐름제어에 의해 데이터를 보낸다. P플래그가 있는 데이터 포함 버퍼의 모든 데이터를 즉시 내보낸다. 수신측에서도 P플래그가 있는 데이터가 수신된 경우, 버퍼의 모든 데이터를 응용 계층으로 올려보낸다.(일반적으로 사용 안한다.)
    • 연결 관련 flag :
      • R(RST) : reset. 연결 재시작 요청
      • S(SYN) : sync. 연결 시작 요청
      • F(FIN) : final. 연결 종료 요청
  • 6) receive wondow : 데이터를 받을 버퍼 사이즈. 상대방에게 흐름제어 정보를 전달한다. (다음에 ack number에 대해 받을거를 기대하고있는데, receive window 수 만큼 ack 없이 데이터를 보낸도 된다. 버퍼가 다 차있는 경우, receive window 를 0으로 보낸다.)
  • 7) checksum : 이 세그먼트에 오류 여부를 판단하는데 사용하는 값이다.
  • 8) Urg data pointer : URG flag가 1인 경우, 마지막 Urgent data의 바이트를 표시한다.

 

3) TCP sequence number와 ACK

sequence number : 세그먼트 데이터의 첫번째 바이트의 번호

ACK : 상대방이 다음에 보낼것으로 예상되는 데이터(누적 방식)

 

Sent & ACKed : 전송되었고 ACK도 받은 데이터 바이트

Window size : 윈도우 사이즈 이내의 데이터는 ACK 여부와 상관 없이 내보내도 되는 데이터 바이트

Sent & not yet ACKed : 전송되었지만 아짐 ACK 받지 못한 데이터 바이트

Usable But not yet sent : 내보낼 수는 있지만, Application이 아직 보내지 않았거나, 세그먼트를 꽉 채울만큼 다 차지 않아서 아직 내보내지 않은 데이터 바이트

Not usable : Window size를 초과하므로 내보내면 안되는 구간

 

4) TCP RTT(round trip time)과 timeout (Timer)

(1) TCP timeout 시간을 설정하는 방법

RTT를 기준으로 timeout 시간을 정한다 (RTT보다는 길어야한다.)

RTT(round  trip time)를 너무 짧게 예측하면, 불필요한 재전송이 발생할 수 있다. 

너무 길게 예측하면, segment 손실에 대한 반응(reaction)이 늦어진다.

 

 

(2) RTT를 예측하는 방법

Sample RTT

: segment 전송부터 ACK 수신까지 시간을 측정한다. 재전송은 무시한다.

 

지수 가중 이동 평균으로 Estimated RTT를 구한다. 

Estimated RTT = (1-a)*Estimated RTT + a * Sample RTT (일반적으로 a = 0.125)

a가 작으므로 현재 Sample RTT의 반영이 크지 않다. 오래된 데이터의 영향은 급격하게 감소한다((1-a)^(과거 회차)*a만큼 반영되므로)

 

Estimate RTT와 실제 RTT간 차이가 큰데, 이를 보안하기 위해

Timeout Interver은 Estimated RTT와 safty margin을 더해 구한다.

 

Estimate RTT로부터 Sample RTT의 편차를 구한다.

DevRTT = (1-B) * DevRT + B * | SampleRTT - EstimatedRTT | (일반적으로 B=0.25)

DevRTT가 크다 = Sample RTT가 Estimated RTT를 많이 벗어난는 의미이므로 Safty Margin을 크게 둬야한다. 

 

Timeout Interval = Estimated RT + 4 * Dev RTT(safty margin)

 

 

Estimated RTT가 실제 RTT보다 큰 경우도 있는데, timeout은 estimated RTT에 * Dev RTT를 더해준 값이므로 premature timeout 보다는 Timeout 시간이 너무 길어 재전송이 늦어지는 경우가 더 많다.

 

premature timeout

: 패킷과 ACK가 정상적으로 전달되지만  전송하는데 걸리는 지연 시간이 timeout period을 초과하는 경우이다. 이 경우, sender는 재전송을 하고 중복처리 과정이 연쇄적으로 일어난다.