본문 바로가기
네트워크

[네트워크] Chap 3.4 - TCP segment structure

by 개발 고양이 2024. 11. 22.

TCP overview

point-to-point

one sender, one receiver
TCP는 1:1 통신만 지원한다. (unicast만 지원하며, multicast는 불가능하다)

 

connection-oriented

TCP는 data 전송 전에 handshaking 과정을 거치면서 control msg를 교환한다.

 

pipelining

window size (w) 내에 있는 패킷들이 ACK 없이도 전송된다.

 

full duplex

같은 connection 안에서 bi-directional data flow가 가능하다. 즉 sender와 receiver의 역할이 고정되어 있지 않고, 양쪽 방향으로 데이터 전송이 가능하다.

 

flow control

sender will not overwhelm receiver

즉 receiver buffer가 얼마나 차있는가(e2e개념)를 보면서, receiver buffer를 초과하지 않도록 제어한다.

 

congestion control

sender will not overwhelm network

즉, 라우터의 output buffer가 넘치지 않도록 제어한다.

 

W = min(rwnd, cwnd)

: window size

= congestion control에 의해 결정되는 cwnd  & flow control에 의해 결정되는 rwnd 중 작은 값

 

reliable, in-order byte stream

byte단위로 order가 맞는지 본다!
즉 application 계층이 보낸 msg 단위로 전송되지 않고 byte단위로 보낸다. 그래서 msg크기가 더 큰 경우 fragmentation이 발생할 수 있고, msg크기가 작은 경우 TCP segment 하나에 2개 이상의 msg가 실려갈 수도 있다.

 

cumulative ACKs

 


TCP segment structure

source port # 와 destination port #는 각각 16bit이다.

 

sequence number (16bits)

byte 단위로 구분되며, 현재 전송하는 byte stream을 나타내기 위해 사용한다.

 

acknowledgement number (16bits)

sender로부터 다음에 도착할 것으로 기대되는 byte의 sequence number가 들어간다.

= ~까지는 잘 받았다는 의미

 

head len (length of TCP header)
:4byte 를 기본 단위로 하는 값을 표기
:만약 이 필드의 값이 5라면 헤더의 길이는 4*5 = 20byte, 즉 옵션이 없는 기본 헤더임을 의미

 

options

헤더의 마지막 부분인 options 필드는 variable length, 즉 가변적이기 때문에 TCP의 헤더의 길이는 고정되어있지 않다.

=> 만약 option이 따로 없는 경우, TCP 헤더의 길이는 20byte가 된다. 


TCP sequence numbers, ACKS

 

초록색 : ACK을 받은 byte들

노란색 : 전송했으나 아직 ACK을 받지 못한 byte들

파란색 : usable하지만(window size) 아직 전송X

 

파란색을 보낼때, sender가 전송하는 TCP의 헤더에서 sequence number 필드에는 파란색 부분의 첫번째 byte를 가리킨다. 위 그림에서 파란색은 6칸이다. 즉 추가로 ACK이 오지 않더라고, 6byte를 보낼 수 있다는 의미이다.

 

sender에서 ACK을 수신할때는 어떨까?

=> flag bit가 A여야 한다.

=> acknowledgement number 필드에는 내가 다음에 받기를 기대하는 sequence number를 넣는다

=> 즉 노란색 부분의 첫번째 byte를 가리킨다!


TCP sequence numbers, ACKS

(Initial sequence number는 TCP connection set-up할때 random하게 pick된다)

  1. 첫번째 segment : client → server (Seq=42, ACK=79)
    Host A에서 user가 입력한 'C'를 데이터로 실어서 B로 전송
    이때 Seq=42, ACK=79 (42, 79는 랜덤하게 pick된 initial sequence number)

  2. 두번째 segment : server → client (Seq=79, ACK=43)
    Host B가 ACK을 보내는 sender가 되므로 Seq = 자신이 수신한 ACK #인 79가 된다.
    (자신이 받은 ACK #가 자신이 보낼 Seq 번호이다)
    Host B는 데이터를 잘 받았으면 Seq number + 1을 server에게 ACK으로 보낸다.

  3.  세번째 segment : client → server (Seq=43, ACK=80)
    받은 ACK 번호가 43이므로 Seq에 43을 담아서 보낸다
    client가 79까지는 잘 받았으므로 ACK에 80을 담아서 보낸다. 

A는 seq = 42로 데이터를 보냈는데, B가 잘 받으면 다음 byte인 43을 ACK으로 보낸다. 그 후 A가 B에게 데이터를 보낼 때에는 43을 seq으로 보낸다.

 

B 입장에서는 자신이 sender이고, A가 receiver이다.

A가 79를 ACK으로 보냈다는건 78까지는 문제없이 받았다는 뜻이므로, Seq=79로 보낸다. 또한 42까지 성공적으로 받았고, 43을 기다린다는 것을 말해줘야 하므로 ACK에 43을 넣어서 A에게 보낸다.


TCP round trip time, timeout

TCP는 reliable한 서비스를 제공하기 때문에, error가 난 경우 retransmission을 해야 한다.

TCP timeout value를 어떻게 설정해야 할까? => RTT보다 약간 길게! 하지만 RTT는 변한다.

 

① too short, timeout이 너무 짧은 경우

premature timeout 발생. 조금만 더 기다리면 되는데 재전송함.

즉 불필요한 retransmission을 해줘야한다.

 

② too long, timeout이 너무 긴 경우

slow reaction 발생.

loss가 발생했을 때 delay가 너무 길어진다.

 

그렇다면 unnecessary retransmission을 줄이고 unnecessary delay도 줄이려면 어떻게 해야할까?

결론부터 말하자면, long timeout value timer로 too short를 막고, fast retransmission으로 too slow를 막는다!

 

how to estimate RTT?

SampleRTT : segment transmission ~ ACK receive 까지 측정한 시간

이때, retransmission한 segment을 이용한 SampleRTT 값은 timeout value 조정에 사용하지 않는다!
왜냐하면, sender가 지금 받은 ack이 original segment에 대한 ack인지, 아니면 우연히 재전송된 ack이 빨리 도착한 건지 구별할 수 없기 때문이다. 


TCP round trip time, timeout

EstimatedRTT = (1-α)*EstimatedRTT + α*SampleRTT

SampleRTT의 i번째 값을 사용해서 EstimatedRTT의 i번째 값을 계산하기 위해서는

그 전에 계산했던 i-1번쨰 RTT를 사용한다!

=> 즉 누적되어있는 값을 사용한다. 누적이 될수록 과거의 EstimatedRTT 값은 영향이 적어지지만, 반영은 된다.

 

timeout을 길게 잡기 위해 safety margin을 크게 잡아서 EstimatedRTT에 더한다!