*신뢰적인 data 전송의 원리
T/L
뿐아니라 A/L, L/L에서도
매우 중요한 문제이다.
매우
중요한 topics
하위계층이 비 신뢰적인 채널인 경우 상위채널에서 신뢰적인 통신을 제공 해야 한다.
# 상태, 액션, 이벤트로 설명한다.
# transport layer 의 TCP가 어떻게 신뢰적인 데이터를 제공하느냐에 대한 설명
*신뢰적 Data transfer
rdt_send() : 하위 rdt에 Data를 전달하기 위해 app가 호출
- 어플리케이션이 TCP에게 메시지를 전달한다.
udt_send() : 비신뢰적인 하위 채널에 Data를 전달하기 위해
rdt가 호출
- TCP가 IP에게 데이터를 주는것
deliver_data() : rdt가 상위 layer에 Data를 전달하기 위해 호출
- IP가 TCP에게 데이터를 주는것
rdt_rcv() : 상위 rdt에 Data를 전달하기 위해 호출
- 세그먼트를 소켓을 통해 어플리케이션에게 전달해준다.
# event : 남이 나에게 해주는 것(누구를 기준으로 하느냐를 알려줘야한다.)
# action : 내가 하는것
sender
# 어플리케이션이 데이터를 주길 기다린다.
# TCP가 메시지를 받아서 세그먼트를 만들어 IP에게 보낸다.
recevier
# IP가 수신자에게 세그먼트를 받는다.
# 데이터를 어플리케이션에게 준다.
# unreliable channel 이라는 채널이 불안정하기 떄문에 TCP가 이렇게 복잡한 작업을 한다.
앞으로의
전개
- 점점 복잡해지는 하위채널을 고려 신뢰적 data 전송 protocol의 송신자 측면과 수신자 측면을 전개
- 단 방향 전송만을 고려 : 이 경우에도 제어 패킷은 양방향 전송이 필요
- FSM으로 표현
참고 : datagram이라는
용어보다는 일반적인 packet이라는 용어를 사용한다.
# 프로토콜 : 이벤트가 발생하면 액션을 취하는 것
# 스테이트먼트 : 상태를 전이하는 것
*rdt 1.0 : 신뢰적인 채널에서 rdt
하위
채널이 완전히 신뢰적인 경우
- no bit error
- no loss of packets
FSM
- 송신측은 상위 layer의 data를 받아 하위 채널로 packet을 전달한다.
- 수신측은 하위 채널에서 packet을 수신하고 data를 상위 layer로 전달한다.
# 동그라미 : 상태
# 직선 위 : 이벤트
# 직선 아래 : 액션
# 화살표 : 상태정의
# wait for call from adove : 위로부터 뭔가 내려오길 기다리고 있는 상태
# wait for call from below : 아래로부터 뭔가 내려오길 기다리고 있는 상태
#
sender
- rdt_send(data) : app가 TCP에게 데이터를 주기 위한 것 ( TCP에선 이벤트)
- packet=make_pkt(data) : 받은 데이터를 패킷으로 만든다.
- udt_send(packet) : 만든 데이터를 보낸다.
# receiver
- wait for call from below : IP로부터 세그먼트가 올라오길 기다리고 있는상태
- rdt_rcv(packet) : IP로부터 패킷을 받는다.
- extract(packet,data) : 패킷으로부터 데이터를 추출
- deliver_data(data) : app 에게 데이터 전달
*rdt 2.0 : 비트 오류가 있는 채널
bit
error이 가능한 채널에서 rdt : packet의
손실이나 순서는 보장
- checksum을 통해 bit error감지
# sender는 손실의 유무를 보낸뒤에 알수 없다.
수신측의 feedback 필요
- acknowledgement (ACKs) : receiver 가 sender 에게 pkt를 잘 받았다는 응답
- negative acknowledgement (NAKs) : receiver 가 sender 에게 pkt에 error또는 장애가 있다는 응답
- sender는 NAK인 경우 pkt 재전송
rdt
2.0에 부가적으로 필요한 protocol (rdt 1.0에 비해서)
- error 검출
- receiver feedback : 제어 msg (ACK,NAK)
- 재전송
- sender 패킷 전송
- receiver 응답 (ack, nack)
- sender 응답을 받고 재송신 판단
- sender 는 nack가 왓다면 재송신
*rdt 2.0 : FSM
sender
wait for call from above : app로 부터 데이터가 오길 기다리는 상태
rdt_send(data) : app로 데이터를 받는다.
sndpkt = make_pak(data, checksum) : 체크섬을 포함한 패킷을 만든다.
udt_send(sndpkt) : ip로 패킷을 보낸다
wait for ack or nak : ack, nak의 응답이 오길 기다리는 상태 변경
rdt_rvc(rcvpkt) && isNAK(rcvpkt) : NAK 응답을 받는다.
udt_send(sndpkt) : 패킷을 다시 보낸다
wait for ack or nak : ack, nak의 응답이 오길 기다리는 상태 변경
rdt_rvc(rcvpkt) && isACK(rcvpkt) : ack 응답을 받는다.
wait for call from above : app로 부터 데이터가 오길 기다리는 상태로 변경
receiver
wait for call from below : IP에서 TCP가 패킷이 도착하길 기다리는 상태
rdt_rcv(rcvpkt)&&corrupt(rcvpkt) : 패킷을 받았으나 패킷이 깨져서 버림
udt_send(NAK) : IP에게 NAK를 보냄
rdt_rcv(rcvpkt)&¬corrupt(rcvpkt) : 패킷을 받고 패킷이 안깨졌다.
extract(rcvpkt,data) : 패킷을 데이터로 변환
deliver_data(data) : TCP가 app에게 데이터를 보낸다.
udt_send(ACK) : IP에게 ACK를 보낸다.
wait for call from below : IP에서 TCP가 패킷이 도착하길 기다리는 상태로 변경
# sender가 데이터가 꺠지는 것을 가정한것
*rdt 2.0 : rcvpkt OK
*rdt 2.0 : rcvpkt
error
1. (sender - TCP 상태) wait for call from above
- app로 부터 데이터가 오길 기다리는 상태
2. (sender - TCP 이벤트) rdt_send(data)
- app로부터 TCP가 데이터를 받는다.
3. (sender - TCP 액션) sndpkt = make_pkt(data, checksum)
- 체크섬을 포함한 패킷을 만든다.
4. (sender - TCP 액션) udt_send(sndpkt)
- TCP는 IP로 세그먼트를 보낸다
5. (sender - TCP 상태) wait for ack or nak
- TCP는 IP로부터 ack, nak의 응답이 오길 기다리는 상태를 변경한다.
6. (receiver - TCP 상태) wait for call from below
- IP에서 TCP가 세그먼트가 도착하길 기다리는 상태
7. (receiver - TCP 이벤트) rdt_rcv(rcvpkt)&&corrupt(rcvpkt)
- IP로부터 패킷을 받았으나 패킷이 깨져서 버림
8. (receiver - TCP 액션) udt_send(NAK)
- TCP는 IP에게 NAK 세그먼트를 보냄
9. (sender - TCP 이벤트) rdt_rvc(rcvpkt) && isNAK(rcvpkt)
- IP로부터 TCP는 NAK 응답을 받음
10. (sender - TCP 액션) udt_send(sndpkt)
- TCP는 IP로 세그먼트를 다시 보낸다.
11. (receiver - TCP 이벤트) rdt_rcv(rcvpkt)&¬corrupt(rcvpkt)
- IP로부터 TCP는 세그먼트를 받고 패킷이 깨지지 않은것을 확인
12. (receiver - TCP 액션) udt_send(NAK)
- TCP는 IP에게 NAK를 보냄
13. (receiver - TCP 액션) extract(rcvpkt,data)
- TCP는 세그먼트를 데이터로 추출
14. (receiver - TCP 액션) deliver_data(data)
- TCP가 APP에게 데이터를 보낸다.
15. (receiver - TCP 액션) udt_send(ACK)
- TCP가 IP에게 ACK를 보낸다.
16. (receiver - TCP 상태) wait for call from below
- IP에서 TCP가 패킷이 도착하길 기다리는 상태로 변경
17. (sender - TCP 이벤트) rdt_rvc(rcvpkt) && isACK(rcvpkt)
- IP로부터 TCP는 ACK 응답을 받는다.
18. (sender - TCP 상태) wait for call from below
- IP에서 TCP가 패킷이 도착하길 기다리는 상태로 변경
*rdt 2.0 : 치명적인 결함
ACK/NAK가 훼손되는 경우
- sender는 receiver쪽에 어떤일이 벌어졌는지 알 수 없다.
- 재전송으로 packet이 중복될 수 있다.
중복을 제어하는 방법
- sender는 pkt에 sequence number를 추가한다.
- ACK나 NAK가 변형되면 sender는 pkt를 재전송한다.
- receiver는 중복된 pkt을 버린다.
- rdt 2.1
- 그래서 시퀀스넘버에 0, 1밖에 없다.
stop and wait
Sender는 pkt 하나를 전송한후 receiver 로 부터 response가 올때까지 대기한다.
->
response가 없으면 계속 기다린다
# ACK/NAK가 훼손되면서 시퀀스 넘버가 나오는 계기가 됨
# 여기서의 시퀀스 넘버는 패킷이 중복되는지 아닌지 확인하기 위한 것
*rdt 2.1
: sender
# 대각선으로 나누면 둘이 똑같다.
# 원래는 시퀀스넘버를 미리 주고 받는다.
상태) wait for call 0
from above
- TCP가 0번 패킷을 보내기 위해서 APP에서 보내는 데이터를 대기 중인 상태
이벤트) rdt_send(data)
- APP로부터 TCP로 데이터를 전달
액션) sndpkt =
make_pkt(0, data, checksum)
- TCP는 시퀀스 넘버 0번과 체크섬과 데이터를 패킷으로 만든다
액션) udt_send(sndpkt)
- TCP는 세그먼트를 IP로 전달한다.
상태) wait for ACK or
NAK 0
- TCP는 0번 패킷에 대한 ACK 혹은 NAK 을 기다리는 상태로 변경 (ACK, NAK에는 시퀀스 넘버가 0번이 포함되지 않음)
이벤트) rdt_rcv(rcvpkt)&&(corrupt(rcvpkt)
|| isNAK(rcvpkt) )
- TCP가 IP로 부터 패킷을 받았는데 패킷이 깨졌거나 NAK다)
액션) udt_send(sndpkt)
- TCP가 IP로 패킷을 다시 보낸다.
이벤트) rdt_rcv(rcvpkt)&¬corrupt(rcvpkt)&&isACK(rcvpkt)
- TCP가 IP로부터 패킷을 받아서 깨지지 않은것과 ACK인지 확인한다.
상태) wait for call 1 from above
- TCP가 1번 패킷을 보내기 위해서 APP에서 보내는 데이터를 대기 중인 상태로 변경된다.
댓글 없음:
댓글 쓰기