이론

TCP 데이터 전송 - rdt

secudb123 2025. 1. 15. 12:45

 

 

*신뢰적인 data 전송의 원리

기본적으로 네트워크 구조 상 발신자와 수신자는 상호 블라인드 관계를 지닌다.

따라 발신자는 수신자가 Data를 수신했는지의 여부를 알지 못한다.

 

하위 계층이 신뢰적인 채널인 경우, 사용하는 Transport Layer의 기능이 적다.

하지만 하위계층이 비신뢰적인 경우, 우리는 Transport Layer에서 rdt protocol을 호출해 신뢰성을 제공한다. 

 

 

 

*용어 및 사용 상징

- rdt: Reliable Data Transfer protocol.

- rdt_rcv: 데이터를 수신하기 위해 rdt를 호출한다.

- rdt_send: 데이터를 전송하기 위해 rdt를 호출한다.

- packet' : 전달받은 패킷. (전달 전에는 '가 없다. 전달 이후에는 오류가 적용될 수 있으므로 구분한다.)

 

이제부턴 State Diagram을 그려 rdt를 호출해 데이터 전송할 때의 이벤트와 액션을 정리한다.

조건은 점진적으로 추가된다.

 


 

<1> rdt 1.0

전제: 하위 채널이 신뢰적이다.

필요 기능: 송/수신

 

 

 

<Sender Side>

 

(1) 최초 상태

상태 : 상위 레이어로부터의 데이터 입력을 대기하는 상태다.

 

(2) 최초 상태에서 이벤트 발생

이벤트 종류 :

rdt_rcv(data). 최초 상태(1)에서 상위 레이어로부터 data가 들어왔다.
액션:

packet=make_pkt(data). 들어온 data를 이용해 packet을 형성한다.

rdt_send(packet). reciever에게 packet을 전송한다.

상태:

최초 상태(1)로 돌아간다. 즉, 상태 변화가 없으므로 다시 데이터 입력을 대기하는 상태이다.

 

 

<Reciever Side>

 

(1) 최초 상태

상태 : 하위 레이어로부터의 패킷 전달을 대기하는 상태이다.

 

(2) 최초 상태에서 이벤트 발생

이벤트 종류 : 

rdt_rcv(packet). 최초 상태(1)에서 하위 레이어로부터 packet이 들어왔다.

액션: 

extract(packet, data). 들어온 packet에서 data를 추출한다.

deliver_data(data). 추출한 data를 상위레이어로 전송시킨다.

상태:

최초 상태(1)로 돌아간다. 즉, 상태 변화가 없으므로 다시 패킷 입력을 대기하는 상태다.

 

 


 

<2> rdt 2.0

전제: 하위채널이 비신뢰적이라, 비트 오류가 존재한다.

추가 기능: 오류 검사, 수신자가 오류 여부를 응답(feedback-NAT/ACK), 재전송

 

*ACK: Acknolodgement. 오류가 없다는 feedback 메세지.

*NAK: Negative Acknolodgement. 오류가 존재한다는 feedback 메세지.

 

 

 

 

 

<Sender Side>

(1) 최초 상태
상태 : 상위 레이어로부터의 데이터 입력을 대기하는 상태이다.

(2) 최초 상태에서 이벤트 발생
이벤트 종류 :

rdt_rcv(data). 상위 레이어로부터 data가 들어왔다.
액션:
spkt=make_pkt(data). 들어온 data를 이용해 spkt란 이름의 패킷을 형성한다.

rdt_send(spkt). 형성한 패킷을 reciever에게 전송한다.

상태:

하위 레이어로부터 오류 검증 응답 패킷의 전달을 대기하는 상태로 변경한다.

액션에 대한 결과로 reciever는 응답(APK/NAK)을 보낼 것이다.

 

(3-1) 응답 대기 상태에서 이벤트 발생

이벤트 종류 :

rdt_rcv(Nrpkt). 하위 레이어로부터 응답 패킷 Nrpkt가 들어왔다.

여기서 Nrpkt는 차후 서술될 <recieve side>에서 reciever가 NAK 응답과 checksum을 이용해 형성한 패킷이다.

즉, Nrpkt가 도착했다는 것은 (2)에서 전달한 패킷이 전송과정 중 오류가 생성되어 reciever에게 도착했다는 것이다.

액션: 

rdt_send(spkt). 오류 패킷이 돌아왔으므로 다시 한번 (2)에서 보냈던 패킷을 재전송한다.
상태:

하위 레이어로부터 오류 검증 응답 패킷의 전달을 대기하는 상태를 유지한다.

 

 

(3-2) 응답 대기 상태에서 이벤트 발생

이벤트 종류 :

rdt_rcv(Arpkt). 하위 레이어로부터 응답 패킷 Arpkt가 들어왔다.
여기서 Arpkt는 차후 서술될 <recieve sida>에서 reciever가 ACK 응답과 checksum을 이용해 형성한 패킷이다.

즉, Arpkt가 도착했다는 것은 (2)에서 전달한 패킷이 전송과정 중 오류없이 정상적으로 reciever에게 도착했다는 것이다.
액션: 

λ (람다). (2)에서 패킷이 제대로 전송되었음을 확인했으므로, 아무런 대응(액션)도 취하지 않는다.
상태:

상위 레이어로부터의 데이터 입력을 대기하는 최초 상태로 돌아간다.

 

 

 

<Reciever Side>

 

(1) 최초 상태
상태 : 하위 레이어로부터의 패킷 전달을 대기중이다.

 

(2-1) 최초 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt)&& corrupt. 하위 레이어로부터 패킷 spkt가 들어왔다. 해당 패킷에는 오류가 존재한다.

 

액션: 

Nrpkt=make_pkt(NAK, chksum). NAK과 checksum을 이용해 패킷 Nrpkt를 형성한다.

rdt_send(Nrpkt). 형성한 Nrpkt를 Sender에게 발송한다.


상태:

하위 레이어로부터의 패킷 전달을 대기중이다. 최초 상태에서 변화가 없다.

 

(2-2)  최초 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt)&& not corrupt. 하위 레이어로부터 패킷 spkt가 들어왔다. 해당 패킷은 오류가 존재하지 않으며, 정상적으로 수신되었다.


액션: 

extract(spkt, data). 전송받은 패킷 spkt에서 data를 추출한다.

deliver_data(data). 상위 레이어로 추출한 data를 전송한다.

Arpkt=make_pkt(APK, chksum). APK와 checksum으로 Sender 에게 전달할 패킷 Arpkt를 생성한다.

rdt_send(Arpkt). 제작한 패킷 Arpkt을 Sender에게 전송한다.

상태:

하위 레이어로부터의 패킷 전달을 대기중이다. 최초 상태에서 변화가 없다.

 

 

 

* rdt 2.0의 결함

- NAK/ACK의 전송 중 결함을 상정하지 않았다.

- 재발송으로 인해 중복 Packet이 발송된다.

→ 해당 결함을 개선한 것이 rdt 2.1이다.

 


 

 

<3> rdt 2.1

 

전제: 하위채널이 비신뢰적이라, 비트 오류가 존재한다.

추가 기능: 오류 검사, 수신자가 오류 여부를 응답(feedback-NAT/ACK), 재전송, NAT/ACK의 결함 시 대응결과, seq #를 지정함으로서 재전송 시 대응(중복 패킷 삭제) 추가.

 

*seq #는 0/1 2가지면 충분하다. 직전 패킷과 현재 패킷만 구별할 수 있으면 되기 때문이다.

 

 

<Sender Side>

 

(1) 최초 상태. 이후 과정에선 S0 상태로 부른다.
상태 :  상위 레이어로부터의 데이터 입력을 대기중이다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 0으로 설정한다.

(2) S0 상태에서 이벤트 발생
이벤트 종류 :
rdt_rcv(data). 상위 레이어로부터 data가 들어왔다.

액션:
spkt=make_pkt(0, data, chksum). 들어온 data로 패킷 spkt를 형성한다. 해당 패킷의 구성요소는 시퀀스 넘버 0, data, checksum이다.

rdt_send(spkt). reciever에게 패킷 spkt를 전송한다.
상태:

하위 레이어로부터 시퀀스 넘버가 0인 응답(APK/NAK)을 대기하는 상태로 변경한다. 이후 과정에선 R0 상태로 부른다.

 

(3-1) R0상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(Arpkt) && corrupt || rdt_rcv(Nrpkt). 하위 레이어로부터 패킷이 전달되었다. 해당 패킷은 오류가 존재하는 Arpkt 패킷, 혹은 모든 Nrpkt 패킷이다. 즉, R0 상태에서 바라던 패킷이 아니다. 
액션: 
rdt_send(spkt). (2)에서 생성한 spkt을 재전송한다. 
상태:

R0 상태를 유지해 다시 패킷응답이 오길 대기한다. 

 

 

(3-2) R0상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(Arpkt) && not corrupt. 오류가 없는 Arpkt 패킷이 전달되었다.
액션: 
λ (람다). (2)에서 패킷이 제대로 전송되었음을 확인했으므로, 아무런 대응(액션)도 취하지 않는다.
상태:

상위 레이어로부터의 새로운 데이터 입력을 대기하는 상태로 변경된다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 1으로 설정하며, 이후 해당 상태를 S1 상태로 기입한다.

 

※ 이후 과정에선 해당 상태에서 바라는 시퀀스 넘버만 다를 뿐, 위와 동일한 대응을 취한다.

 

더보기

 

(4) S1상태에서 이벤트 발생

이벤트 종류 :
rdt_rcv(data). 상위 레이어로부터 data가 들어왔다. 

액션:
spkt=make_pkt(1, data, chksum). 들어온 data로 패킷 spkt를 형성한다. 해당 패킷의 구성요소는 시퀀스 넘버 1, data, checksum이다.

rdt_send(spkt). reciever에게 패킷 spkt를 전송한다.
상태:

하위 레이어로부터 시퀀스 넘버가 1인 응답(APK/NAK)을 대기하는 상태로 변경한다. 이후 과정에선 R1 상태로 부른다.

 

(5-1) R1 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(Arpkt) && corrupt || rdt_rcv(Nrpkt). 하위 레이어로부터 패킷이 전달되었다. 해당 패킷은 오류가 존재하는 Arpkt 패킷, 혹은 모든 Nrpkt 패킷이다. 즉, R1 상태에서 바라던 패킷이 아니다. 
액션: 
rdt_send(spkt). (4)에서 생성한 spkt을 재전송한다. 
상태:

R1 상태를 유지해 다시 패킷응답이 오길 대기한다. 

 

 

(5-2) R1 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(Arpkt) && not corrupt. 오류가 없는 Arpkt 패킷이 전달되었다.
액션: 
λ (람다). (2)에서 패킷이 제대로 전송되었음을 확인했으므로, 아무런 대응(액션)도 취하지 않는다.
상태:

상위 레이어로부터의 새로운 데이터 입력을 대기하는 상태로 변경된다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 0으로 설정하므로, 이 상태는 곧 초기 상태인 S0 상태이다.

 

이후 (1)부터 다시 진행할 수 있다.

 

 

 

 

 

 

<Reciever Side>

 

(1) 최초 상태
상태 : 하위 레이어로부터의 패킷 전달을 대기중이다. 해당 상태에서 들어온 데이터는 시퀀스 넘버가 0이어야한다. 해당 상태를 A0 상태로 기입한다.

(2-1) A0 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt)&& corrupt. 하위 레이어로부터 패킷 spkt이 들어왔다. 해당 패킷은 오류가 존재한다.
액션: 
Nrpkt=make_pkt(NAK, chksum). NAK와 checksum으로 패킷 Nrpkt를 생성한다.

rdt_send(Nrpkt). 생성한 Nrpkt를 Sender에게 전달한다.

상태:

A0상태. 다시 패킷이 들어오기를 대기한다.

 

(2-2) A0 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(spkt) && not corrupt && seq(0) 하위 레이어로부터 패킷 spkt이 들어왔다. 해당 패킷에는 오류가 존재하지 않으나, 시퀀스 넘버가 1이다. 즉, 현 상황에서 들어와야하는 패킷이 아니다.
액션: 
Arpkt=make_pkt(ACK, chksum). ACK와 checksum으로 패킷 Arpkt를 생성한다.

rdt_send(Arpkt). 생성한 Arpkt를 Sender에게 전달한다. Sender는 전송한 패킷이 제대로 전달된 것을 확인했으므로, 이후  같은 패킷을 다시 보내지 않을 것이다.

delete_pkt(spkt). 하위레이어로부터 전달받았던 패킷 spkt를 폐기한다.

상태:

A0상태. 다시 패킷이 들어오기를 대기한다.

 

(2-3) A0 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(spkt) && not corrupt && seq(0) 하위 레이어로부터 패킷 spkt이 들어왔다. 해당 패킷에는 오류가 존재하지 않으며, 시퀀스 넘버가 0으로 적합하다.
액션: 

extract(spkt, data). 전송받은 패킷 spkt에서 data를 추출한다.

deliver_data(data). 상위 레이어로 추출한 data를 전송한다.

Arpkt=make_pkt(APK, chksum). APK와 checksum으로 Sender 에게 전달할 패킷 Arpkt를 생성한다.

rdt_send(Arpkt). 제작한 패킷 Arpkt을 Sender에게 전송한다.

상태:

하위 레이어로부터의 패킷 전달을 대기하는 상태가 된다. 단, 이미 시퀀스 넘버가 0인 패킷을 정상적으로 전달받았으므로 해당 상태에서 들어올 패킷의 시퀀스 넘버는 1이어야한다. 시퀀스 넘버가 1인 패킷이 들어와야하는 상태를 이후 A1 상태로 기입한다.

 

※ 이후 과정에선 해당 상태에서 바라는 시퀀스 넘버만 다를 뿐, 위와 동일한 대응을 취한다.

 

더보기

 

(3-1) A1 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(spkt)&& corrupt. 하위 레이어로부터 패킷 spkt이 들어왔다. 해당 패킷은 오류가 존재한다.
액션: 
Nrpkt=make_pkt(NAK, chksum). NAK와 checksum으로 패킷 Nrpkt를 생성한다.

rdt_send(Nrpkt). 생성한 Nrpkt를 Sender에게 전달한다.

상태:

A1상태. 다시 패킷이 들어오기를 대기한다.

 

(3-2) A1 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(spkt) && not corrupt && seq(0). 하위 레이어로부터 패킷 spkt이 들어왔다. 해당 패킷에는 오류가 존재하지 않으나, 시퀀스 넘버가 0이다. 즉, 현 상황에서 들어와야하는 패킷이 아니다.
액션: 
Arpkt=make_pkt(ACK, chksum). ACK와 checksum으로 패킷 Arpkt를 생성한다.

rdt_send(Arpkt). 생성한 Arpkt를 Sender에게 전달한다. Sender는 전송한 패킷이 제대로 전달된 것을 확인했으므로, 이후  같은 패킷을 다시 보내지 않을 것이다.

delete_pkt(spkt). 하위레이어로부터 전달받았던 패킷 spkt를 폐기한다.

상태:

A1상태. 다시 패킷이 들어오기를 대기한다.

 

(3-3) A1 상태에서 이벤트 발생

이벤트 종류 : 
rdt_rcv(spkt) && not corrupt && seq(1) 하위 레이어로부터 패킷 spkt이 들어왔다. 해당 패킷에는 오류가 존재하지 않으며, 시퀀스 넘버가 1으로 적합하다.
액션: 

extract(spkt, data). 전송받은 패킷 spkt에서 data를 추출한다.

deliver_data(data). 상위 레이어로 추출한 data를 전송한다.

Arpkt=make_pkt(APK, chksum). APK와 checksum으로 Sender 에게 전달할 패킷 Arpkt를 생성한다.

rdt_send(Arpkt). 제작한 패킷 Arpkt을 Sender에게 전송한다.

상태:

시퀀스 넘버가 1인 패킷을 정상적으로 전달받았으므로, A0 상태로 변경된다.

 

이후 (1)부터 다시 진행할 수 있다.

 

 


 

 

 

<3> rdt 2.2

 

전제: 하위채널이 비신뢰적이라, 비트 오류가 존재한다.

2.1과의 차이점: 수신자가 NAK를 전달하지 않고, ACK만 전달한다.

 

발신자는 중복된 ACK 패킷을 통해 발신한 패킷의 수신여부를 알 수 있다.

 

<Sender Side>

 

(1) 최초 상태
상태 : 상위 레이어로부터의 데이터 입력을 대기중이다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 0으로 설정한다. 이후 과정에선 S0 상태로 부른다.

(2) S0 상태에서 이벤트 발생
이벤트 종류 :
rdt_rcv(data). 상위 레이어로부터 data가 들어왔다.
액션:
spkt=make_pkt(0, data, chksum). 들어온 data로 패킷 spkt를 형성한다. 해당 패킷의 구성요소는 시퀀스 넘버 0, data, checksum이다.

rdt_send(spkt). reciever에게 패킷 spkt를 전송한다.

상태:

하위 레이어로부터 시퀀스 넘버가 0인 ACK 응답을 대기하는 상태로 변경한다. 이후 과정에선 R0 상태로 부른다.

 

(3-1) R0상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && ( corrupt || Seq(1) ). 하위 레이어로부터 패킷 Arpkt이 전달되었다. 해당 패킷은 오류가 존재하거나 시퀀스 넘버가 1인 패킷이다. 즉, R0 상태에서 바라던 패킷이 아니다. 
액션: 
rdt_send(spkt). (2)에서 생성한 spkt을 재전송한다. 해당 spkt는 시퀀스 넘버가 0이다.
상태:
R0 상태를 유지해 다시 패킷 응답이 오길 대기한다. 

 

(3-2) R0상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && not corrupt  &&  Seq(0). 오류가 없는 Arpkt 패킷이 전달되었다. 해당 패킷의 시퀀스 넘버는 0이다. 즉, R0 상태에서 바라던 패킷이다. 
액션: 
λ (람다). (2)에서 패킷이 제대로 전송되었음을 확인했으므로, 아무런 대응(액션)도 취하지 않는다.
상태:
상위 레이어로부터의 새로운 데이터 입력을 대기하는 상태로 변경된다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 1으로 설정하며, 이후 해당 상태를 S1 상태로 기입한다.

 

※ 이후 과정에선 해당 상태에서 바라는 시퀀스 넘버만 다를 뿐, 위와 동일한 대응을 취한다.

 

더보기

 

(4) S1 상태에서 이벤트 발생
이벤트 종류 :
rdt_rcv(data). 상위 레이어로부터 data가 들어왔다.
액션:
spkt=make_pkt(1, data, chksum). 들어온 data로 패킷 spkt를 형성한다. 해당 패킷의 구성요소는 시퀀스 넘버 1, data, checksum이다.

rdt_send(spkt). reciever에게 패킷 spkt를 전송한다.

상태:

하위 레이어로부터 시퀀스 넘버가 1인 ACK 응답을 대기하는 상태로 변경한다. 이후 과정에선 R1 상태로 부른다.

 

(5-1) R1상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && ( corrupt || Seq(0) ). 하위 레이어로부터 패킷 Arpkt이 전달되었다. 해당 패킷은 오류가 존재하거나 시퀀스 넘버가 0인 패킷이다. 즉, R1 상태에서 바라던 패킷이 아니다. 
액션: 
rdt_send(spkt). (2)에서 생성한 spkt을 재전송한다. 해당 spkt는 시퀀스 넘버가 1이다.
상태:
R1 상태를 유지해 다시 패킷 응답이 오길 대기한다. 

 

(3-2) R1 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && not corrupt  &&  Seq(1). 오류가 없는 Arpkt 패킷이 전달되었다. 해당 패킷의 시퀀스 넘버는 1이다. 즉, R1 상태에서 바라던 패킷이다. 
액션: 
λ (람다). (2)에서 패킷이 제대로 전송되었음을 확인했으므로, 아무런 대응(액션)도 취하지 않는다.
상태:

상위 레이어로부터의 새로운 데이터 입력을 대기하는 상태로 변경된다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 0으로 설정하므로, 이 상태는 곧 초기 상태인 S0 상태이다.

 

이후 (1)부터 다시 진행할 수 있다.

 

 

 

 

 

 

 

<Reciever Side>

 


(1) 최초 상태
상태 : 하위 레이어로부터의 패킷 전달을 대기중이다. 해당 상태에서 들어온 데이터는 시퀀스 넘버가 0이어야한다. 해당 상태를 A0 상태로 기입한다.

 

(2-1) A0 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt) && ( corrupt || Seq (1) ). 하위 레이어로부터 패킷 spkt이 전달되었다. 해당 패킷은 오류가 존재하거나 시퀀스 넘버가 1인 패킷이다. 즉, A0 상태에서 바라던 패킷이 아니다.

Apkt=make_pkt(APK(1), chksum). 전달받은 패킷의 시퀀스 넘버가 1이었음을 의미하는 ACK(1)과 checksum으로 패킷 Arpkt를 생성한다.

(※ 이전 과정에서 Arpkt 패킷이 만들어졌다면 생략 가능)

rdt_send(Arpkt). Sender에게 Arpkt 패킷을 전달한다. Sender는 해당 패킷응답을 통해 자신이 시퀀스 넘버가 잘못된 파일을 전달했거나 전송과정 중 패킷에 오류가 생겼음을 인지해, 다음 전송때는 시퀀스 넘버가 0인 패킷을 보내게 된다.

delete_pkt(spkt). 하위레이어로부터 전달받았던 패킷 spkt를 폐기한다.

상태:

A0상태. 다시 패킷이 들어오기를 대기한다.

 

(2-2) A0 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt) && not corrupt && seq(0). 하위 레이어로부터 패킷 spkt이 전달되었다. 해당 패킷에는 오류가 존재하지 않으며, 시퀀스 넘버가 0으로 적합하다.

액션:

extract(spkt, data). 전송받은 패킷 spkt에서 data를 추출한다.

deliver_data(data). 상위 레이어로 추출한 data를 전송한다.

Arpkt=make_pkt(APK(0), chksum). 전달받은 패킷의 시퀀스 넘버가 0이었음을 의미하는 APK(0)와 checksum으로 Sender 에게 전달할 패킷 Arpkt를 생성한다.

(※ 이전 과정에서 Arpkt 패킷이 만들어졌다면 생략 가능)

rdt_send(Arpkt). 제작한 패킷 Arpkt을 Sender에게 전송한다.

상태:

하위 레이어로부터의 패킷 전달을 대기하는 상태가 된다. 단, 이미 시퀀스 넘버가 0인 패킷을 정상적으로 전달받았으므로 해당 상태에서 들어올 패킷의 시퀀스 넘버는 1이어야한다. 시퀀스 넘버가 1인 패킷이 들어와야하는 상태를 이후 A1 상태로 기입한다.

 

※ 이후 과정에선 해당 상태에서 바라는 시퀀스 넘버만 다를 뿐, 위와 동일한 대응을 취한다.

 

더보기

 

(3-1) A1 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt) && ( corrupt || Seq (0) ). 하위 레이어로부터 패킷 spkt이 전달되었다. 해당 패킷은 오류가 존재하거나 시퀀스 넘버가 0인 패킷이다. 즉, A1 상태에서 바라던 패킷이 아니다.

Apkt=make_pkt(APK(0), chksum). 전달받은 패킷의 시퀀스 넘버가 0이었음을 의미하는 ACK(1)과 checksum으로 패킷 Arpkt를 생성한다.

(※ 이전 과정에서 Arpkt 패킷이 만들어졌다면 생략 가능)

rdt_send(Arpkt). Sender에게 Arpkt 패킷을 전달한다. Sender는 해당 패킷응답을 통해 자신이 시퀀스 넘버가 잘못된 파일을 전달했거나 전송과정 중 패킷에 오류가 생겼음을 인지해, 다음 전송때는 시퀀스 넘버가 1인 패킷을 보내게 된다.

delete_pkt(spkt). 하위레이어로부터 전달받았던 패킷 spkt를 폐기한다.

상태:

A1상태. 다시 패킷이 들어오기를 대기한다.

 

(3-2) A1 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(spkt) && not corrupt && seq(1). 하위 레이어로부터 패킷 spkt이 전달되었다. 해당 패킷에는 오류가 존재하지 않으며, 시퀀스 넘버가 1으로 적합하다.

액션:

extract(spkt, data). 전송받은 패킷 spkt에서 data를 추출한다.

deliver_data(data). 상위 레이어로 추출한 data를 전송한다.

Arpkt=make_pkt(APK(1), chksum). 전달받은 패킷의 시퀀스 넘버가 1이었음을 의미하는 APK(1)와 checksum으로 Sender 에게 전달할 패킷 Arpkt를 생성한다.

(※ 이전 과정에서 Arpkt 패킷이 만들어졌다면 생략 가능)

rdt_send(Arpkt). 제작한 패킷 Arpkt을 Sender에게 전송한다.

상태:

하위 레이어로부터의 패킷 전달을 대기하는 상태가 된다. 단, 이미 시퀀스 넘버가 1인 패킷을 정상적으로 전달받았으므로 해당 상태에서 들어올 패킷의 시퀀스 넘버는 1이어야한다. 따라서 A0 상태로 복귀한다.

 

이후 (1)부터 다시 진행할 수 있다.

 

 

 


 

<4> rdt 3.0

기본 전제: 하위채널이 비신뢰적이라, 비트 오류가 존재한다.

추가 가정: 전송한 패킷이 전송과정 중에 지연되거나, 사라질 수 있다. (합리적인 시간 안에 도착하지 않아, 결과적으로 지연이 발생한다.)

이에 따라 타임 아웃 기능을 추가한다.

 

즉, Coutdown timer를 추가해 합리적 시간만큼 ACK 패킷 응답이 돌아오지 않으면, Sender는 패킷을 재전송한다.

<Sender Side>

 

(1) 최초 상태
상태 : 상위 레이어로부터의 데이터 입력을 대기중이다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 0으로 설정한다. 이후 과정에선 S0 상태로 부른다.

(2-1)

S0 상태에서 이벤트 발생

이벤트 종류 :
rdt_rcv(Arpkt). 하위 레이어로부터 응답 패킷이 들어왔다. 오류 여부는 중요치 않다. S0 상태는 응답 패킷을 대기하는 상태가 아니다.
액션:
λ. 아무런 액션도 취하지 않는다.

상태:

S0 상태를 유지한다.

 

(2-2) S0 상태에서 이벤트 발생
이벤트 종류 :
rdt_rcv(data). 상위 레이어로부터 data가 들어왔다.
액션:
spkt=make_pkt(0, data, chksum). 들어온 data로 패킷 spkt를 형성한다. 해당 패킷의 구성요소는 시퀀스 넘버 0, data, checksum이다.

rdt_send(spkt). reciever에게 패킷 spkt를 전송한다.

start_timer. contdown timer를 가동시작한다.

상태:

하위 레이어로부터 시퀀스 넘버가 0인 ACK 응답을 대기하는 상태로 변경한다. 이후 과정에선 R0 상태로 부른다.

 

 

(3-1) R0상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && ( corrupt || Seq(1) ). 하위 레이어로부터 패킷 Arpkt이 전달되었다. 해당 패킷은 오류가 존재하거나 시퀀스 넘버가 1인 패킷이다. 즉, R0 상태에서 바라던 패킷이 아니다. 
액션: 
λ. 아무런 액션도 취하지 않는다.
상태:
R0 상태를 유지해 다시 패킷 응답이 오길 대기한다. 

 

 

(3-2) R0상태에서 이벤트 발생
이벤트 종류 : 
timeout. 하위 레이어로부터 패킷이 합리적인 시간내로 도착하지 않았다.
액션: 
rdt_send(Spkt). reciever에게 (2-2)에서 형성한 Spkt 패킷을 재전송한다.

start_timer. contdown timer를 재시작한다.


상태:
R0 상태를 유지해 다시 패킷 응답이 오길 대기한다. 

 

(3-3) R0상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && not corrupt  &&  Seq(0). 오류가 없는 Arpkt 패킷이 전달되었다. 해당 패킷의 시퀀스 넘버는 0이다. 즉, R0 상태에서 바라던 패킷이다. 
액션: 
stop_timer. 기존에 가동했던 contdown timer를 중지한다. 이후 패킷을 새로 보낼때 재가동할 것이다.
상태:
상위 레이어로부터의 새로운 데이터 입력을 대기하는 상태로 변경된다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 1으로 설정하며, 이후 해당 상태를 S1 상태로 기입한다.

 

※ 이후 과정에선 해당 상태에서 바라는 시퀀스 넘버만 다를 뿐, 위와 동일한 대응을 취한다.

더보기

(4-1) S1상태에서 이벤트 발생

이벤트 종류 :
rdt_rcv(Arpkt). 하위 레이어로부터 응답 패킷이 들어왔다. 오류 여부는 중요치 않다. S1 상태는 응답 패킷을 대기하는 상태가 아니다.
액션:
λ. 아무런 액션도 취하지 않는다.

상태:

S1 상태를 유지한다.

 

(4-2) S1 상태에서 이벤트 발생
이벤트 종류 :
rdt_rcv(data). 상위 레이어로부터 data가 들어왔다.
액션:
spkt=make_pkt(1, data, chksum). 들어온 data로 패킷 spkt를 형성한다. 해당 패킷의 구성요소는 시퀀스 넘버 1, data, checksum이다.

rdt_send(spkt). reciever에게 패킷 spkt를 전송한다.

start_timer. contdown timer를 가동시작한다.

상태:

하위 레이어로부터 시퀀스 넘버가 1인 ACK 응답을 대기하는 상태로 변경한다. 이후 과정에선 R1 상태로 부른다.

 

 

(5-1) R1상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && ( corrupt || Seq(0) ). 하위 레이어로부터 패킷 Arpkt이 전달되었다. 해당 패킷은 오류가 존재하거나 시퀀스 넘버가 0인 패킷이다. 즉, R1 상태에서 바라던 패킷이 아니다. 
액션: 
λ. 아무런 액션도 취하지 않는다.
상태:
R1 상태를 유지해 다시 패킷 응답이 오길 대기한다. 

 

 

(5-2) R1상태에서 이벤트 발생
이벤트 종류 : 
timeout. 하위 레이어로부터 패킷이 합리적인 시간내로 도착하지 않았다.
액션: 
rdt_send(Spkt). reciever에게 (4-1)에서 형성한 Spkt 패킷을 재전송한다.

start_timer. contdown timer를 재시작한다.


상태:
R1 상태를 유지해 다시 패킷 응답이 오길 대기한다. 

 

(3-3) R1 상태에서 이벤트 발생
이벤트 종류 : 
rdt_rcv(Arpkt) && not corrupt  &&  Seq(1). 오류가 없는 Arpkt 패킷이 전달되었다. 해당 패킷의 시퀀스 넘버는 1이다. 즉, R1 상태에서 바라던 패킷이다. 
액션: 
stop_timer. 기존에 가동했던 contdown timer를 중지한다. 이후 패킷을 새로 보낼때 재가동할 것이다.

 

상태:
상위 레이어로부터의 새로운 데이터 입력을 대기하는 상태로 변경된다. 해당 상태에서 입력된 데이터는 시퀀스 넘버를 0으로 설정하므로, 곧 초기 상태인 S0 상태로 돌아간 것이다.

 

 

<Reciever Side>

2.2 와 동일하다.

 

 

<ex>

몇 가지 상황을 가정해, 3.0의 진행 과정을 설명해보았다.

//이미지 추가!!!

 

 


 

 

지금까지 가정한 방법은, 한번에 1개의 패킷만을 전송하고 응답을 대기하므로 stop-and-wait 방식이다. 즉, 지연 및 소실이 존재하면 대기 시간이 길다!

이를 위해 Pipelined protocol이 고안되었다.

 

* Pipelining

- Sender에게 ACK를 기다리지 않고 여러개의 패킷 전송을 허용하는 것을 말한다. 한번에 여러 데이터를 처리하므로, rdt 성능이 향상된다.

- Pipelining 을 위해선 시퀀스 넘버의 범위가 증가되어야한다. 또한 sender와 reciever는 하나 이상의 패킷을 buffering해야한다.

- 종류: go-Back-N, selevtive repeat

 

 

*어휘

- window: 한번에 전송할 수 있는 패킷의 개수. 즉, 허용가능한 시퀀스 넘버의 범위이다.

- sendbase: window 내에서 확인되지 않은 가장 오래된 패킷을 말한다. timer가 존재하는 장소이며, timeout의 기준이 된다.

 

 

 

 

<5> go-Back-N

 

* go-Back-N의 기능

- Timeout 발생시 송신되었으나 ACK가 돌아오지 않은, 모든 미확인 패킷을 재전송한다.

- ACK는 누적된다. ACK3은, 패킷 3만의 ACK가 아니라 최초의 패킷부터 3까지의 모든 ACK를 의미한다.

 

 

 

 

 

<6>  Selevtive repeat

- Reciever가 수신한 패킷에 대한 개별적인 ACK가 요구된다. 순서가 틀린 pkt는 하위 seq#를 가진 pkt가 수신될 때까지 buffering 되었다가 seq # 순서대로 상위 레이어에 저달된다.

- Sender는 ACK가 없는 pkt에 대해서만 재전송한다. sender의 timer는 ACK가 없는 각각의 pkt에 대해 유지된다.

- Sender의 window는 send_base pkt에 대한 ACK를 받아야 이동된다.

※ Go-Back-N에서는 누적된 ACK를 사용했으므로 send_base pkt의 ACK를 받지 못해도 이동이 가능했다.