Reliable Data Trasnfer Protocol (rdt)
- rdt_send: 하위 rdt에 전달하기 위해 위에 app에서 호출
- udt_send: unreliable 채널을 통해서 패킷을 전송하기 위해 rdt에서 호출
- rdt_rcv: 상위 rdt에 전달하기 위해 호출
- deliver_data: rdt에서 상위 app에 전달하기 위해 호출
rdt 3.0: channels with errors and loss
- sender는 ack를 위해 합리적인 시간을 기다림
- ack가 안오면 재전송 (중복 패킷이 들어오면 패킷은 무시, ack는 보내줌)
- 만약 패킷이 loss가 아니라 그냥 delayed면 중복 발생 -> seq #가 해결
* stop-and-wait로 구현됨 -> 비효율적
u(sender) = (L/R) / (L/R + RTT) // L/R은 transmission delay (밀어넣기)
* pipelined protocols
- multiple inflight(전송 중인 패킷 수) 보내자, stop-and-wait는 1임
- seq # 증가, 버퍼링 필요
-> go-back-N, selective repeat 2종류가 많이 사용됨
Pipelined protocols: overview
* Go-Back-N
- cumulative ack 사용
- 타이머 하나 사용 (가장 먼저 보낸 ack 받지 못한 패킷에 대해)
- 처음 제대로 안 온 패킷부터 다 다시 전송
* Selective Repeat
- individual ack 사용
- 각각의 packet에 대해 타이머 사용
- 타임아웃된 패킷에 대해서만 재전송
* TCP는 rdt3.0, go-back-n, selective repeat 다 섞어서 씀
Go-Back-N
window size: n개까지 한번에 보낼 수 있음
send base: 윈도우의 첫번째 패킷
nextseqnum: 다음으로 보내질 패킷의 시퀀스 넘버
- cumulative ack: ack(n)은 n번까지 받았다는 뜻
ack(n) 받으면 n+1로 윈도우 슬라이딩 가능
- 타이머는 하나만 유지
- timeout(n): n부터 다 재전송
- 순서대로 받은 애들 중에 젤 큰 애를 ack로 보냄 (중복 ack 올 수도 있음)
- 중복 ack는 버리거나 buffer에 저장해두거나
Selective Repeat
- 잘 들어온 패킷에 대해 각각 ack 보낼 수 있음
- 패킷마다 타이머 유지
- timeout(n): packet n만 재전송, 타이머 재시작
- ack(n) in [sendbase, sendbase+N-1] (n번 패킷 잘 받음~)
구멍났던데 채워지면 다음 노란색으로 슬라이딩
- packet(n) in [rcvbase, rcvbase+N-1]
send ack(n), out-of-order는 buffer (ack도 보내지만 슬라이딩 못함),
in-order는 전달하고 슬라이딩
- packet n in [rcvbase-N, rcvbase-1] (이전 윈도우)
ack(n), ack만 보내고 무시
- otherwise: 그냥 무시
Connection-oriented transport: TCP 😋
- 일대일 통신, reliable, in-order
- cumulative ack, pipelining, connection-oriented
- flow controlled
* TCP segment structure
- 헤더 20바이트 (udp 헤더는 8바이트)
- sequence number: 데이터의 첫번째 바이트 번호
- ack number: 다음으로 기대되는 seq #
- C,E: congestion notification
- RST, SYN, FIN: 강제 종료, TCP 커넥션 연결, TCP 정상 종료
- receive window: receiver가 받을 수 있는 빈 공간의 크기 (for flow control)
- checksum
- urg data pointer
TCP RTT, timeout
* sampleRTT: segement 전송 ~ ack 도착할 때까지의 시간 측정
* EstimatedRTT = (1-a) * EstimatdeRTT + a * SampleRTT (a=0/125)
-> EstimatedRTT는 평균, 새로운 sampleRTT를 얻자마자 EstimatedRTT를 갱신함
* DevRTT는 sampleRTT가 EstimatedRTT로부터 얼마나 많이 벗어났는지에 대한 예측
DevRTT= (1-b) * DevRTT + b*|SampleRTT - EstimatedRTT| (b=0.25)
* TimeoutInterval = EstimatedRTT+ 4*DevRTT (DEVrtt가 safe margin값)
TimeoutInterval은 EstimatedRTT보다 크거나 같아야함
그래도 너무 커도 안됨 -> 변동에 따라 여유값이 바뀜
그래서 여유값으로 DevRTT 사용함
TCP Sender
* application으로부터 data 받았을 때
- segment 만들고 seq #에 데이터의 첫번째 바이트의 숫자 집어넣고 타이머 시작
타이머는 1개임 (go-back-n 스타일)
* timeout
- 타임아웃 발생한 패킷 재전송, 타이머 재시작
* ack received
- unAcked된 segment 있었으면 update하고 다음 unacked된 패킷에 대한 타이머 시작
TCP Receiver
* 기대하던 애가 도착하면: delayed ack, 0.5초정도 다음 ack를 기다렸다가 안 오면 그냥 전송
* ack가 보내지기 위해 준비하고 있을 때 기대하던 애가 도착하면:
즉각적으로 cumulative ack 보냄
* 순서 잘못된 애가 들어오면: 즉각적으로 중복 ack 보냄
* gap을 채우는 애가 도착: 즉각적으로 ack 보내고 슬라이딩 가능
- 누적 ack는 이전의 lost ack를 커버할 수 있음
TCP fast retransmit (타임아웃 발생 안해도 재전송)
- sender가 3개의 중복 ack를 받았다면 가장 작은 seq#의 unACKed segment를 재전송