[Network] Transport Layer 2 - 신뢰성있는 데이터 전송 원리 (rdt)

chxghee·2024년 10월 13일

TCP에 대해 알기 전에 TCP에서 제공하는 신뢰성있는 데이터 전송 원리에 대해 알아보자

신뢰성있는 데이터 전송이 복잡한 이유는 네트워크 레이어 같이 unreliable한 채널 위에서 신뢰성있는 데이터 전송을 구현해야 하기 때문에 어렵다.

송신자는 메세지가 잘 갔는지 확인 할 수 없다.

  • rdt : 신뢰적인 데이터 전송(reliable data transfer) 프로토콜을 나타낸다. rdt_s

  • 가정) 송신 -> 수신으로의 단방향 데이터 전송을 가정한다.

    	하지만 단방향 데이터 전송만 생각하더라도 프로토콜의 송신 측과 수신 측이 양방향으로 패킷을 전달할 필요가 있다.
    	(송수신 측은 전송 데이터를 포함하는 패킷을 교환외에 **`제어 패킷`을 양쪽으로 전송한다.**)
  • rdt의 송신 측과 수신 측 모두 udt_send()를 호출함으로써 다른 쪽에 패킷을 전송한다.

  • udt : 비신뢰적인 데이터 전송(unreliable data transfer)을 나타냄

rdt 1.0

rdt 1.0이란?
1. data 전송시 에러 X
2. data 전송시 loss X 인 상황

이런 단순한 상황에서는 위와 같이 송수신자의 FSM모델이 분리되어 있다.

rdt 2.0

rdt 2.0이란?
1. data 전송시 에러 발생 가능
2. data 전송시 loss X 인 상황
3. ACK/NAK 패킷 손상 X
4. 전송 후 대기(stop-and-wait): 데이터를 주고 수신자의 피드백을 기다림

  • 그렇다면 에러가 발생했을 때 수신자송신자에게 에러 발생을 알려야 오류를 처리할 수 있다.

  • 오류의 검출은 checksum을 통해 발견한다.

  • 수신자 피드백 (1 bit 표현 0/1)
    ACK : 긍정 확인응답(positive acknowledgment, “OK”)
    NCK : 부정 확인응답(negative acknowledgment, “그것을 반복해주세요”)
    -> retransmission

송신자

  1. 왼쪽 상태 - 어플에서 데이터를 주기를 기다림

    rdt_sent(data) 이벤트가 발생
    1) 패킷을 만들고 수신자에 보냄
    2) 오른쪽 상태로 전이

  2. 오른쪽 상태 - 수신자의 ACK 또는 NAK 패킷을 기다린다.
    1) ACK - 왼쪽상태 전이
    2) NAK - retransmission

이렇게 하면 송신자는 데이터가 잘 갔는지 확인할 수 있게 된다.

수신자

  • 단일 상태를 갖는다.

  • 패킷이 도착했을 때, 수신자는 수신된 패킷이 손상되었는지 아닌지에 따라 ACK 또는 NAK로 응답한다.

rdt 2.0 의 문제

1. ACK/NAK 패킷이 손상될 수 있다

만약 ACK 또는 NAK가 손상되었다면,
송신자는 수신자가 전송된 데이터의 마지막 부분을 올바르게 수신했는지를 알 방법이 없다.

2. 중복 패킷(duplicate packet)

단순히 재전송을 하기 때문에
수신자 입장에서는 ACK를 보냈는데 상대가 ACK를 못받아 재전송을 하는데,
도착하는 패킷이 새로운 데이터를 포함하고 있는 것인지 아니면 재전송인지를 알 수 없다.

rdt 2.1

rdt 2.1이란?
1. data 전송시 에러 발생 가능
2. data 전송시 loss X 인 상황
3. ACK/NAK 패킷 손상 가능(loss는 아님)
4. 전송 후 대기(stop-and-wait): 데이터를 주고 수신자의 피드백을 기다림

송신자가 시퀀스 넘버를 패킷에 붇이는 것으로 해결할 수 있다.

  • 송신자는 시퀀스 넘버를 포함하여 보낸다
    • ACK - 다음번에 보내는 새 패킷은 시퀀스 가 이전과 달라짐
    • NCK를 받아 다시 보내야 할 떄 - 같은 시퀀스의 패킷을 보냄
  • corrupt는 패킷의 손상 유무를 나타냄

송신자

  • 송신자는 시퀀스를 번갈아가 가면서 패킷을 전송한다.
  • 송신자는 상태가 4개 (어플에서 데이터 내려오길 기다림 / 피드백 패킷 받기를 기다림)

수신자

  • 다른 시퀀스가 오면 (Wait for 1 상태에서 0 패킷이 수신되면)

    이는 중복된 패킷이거나 잘못된 순서로 패킷이 도착한 것을 의미한다.

  • 이 경우 프로토콜은 중복 데이터를 다시 처리하지 않고, 마지막으로 정상적으로 수신된 패킷에 대한 ACK(확인 응답)를 다시 보낸다.

  1. Wait for 1 상태는 시퀀스 번호가 1인 패킷을 기다리는 상태.

  2. 그러나 시퀀스 번호가 0인 패킷이 도착하면, 이는 이미 수신된 패킷이거나 잘못된 순서로 도착한 패킷이다

  3. 이때 프로토콜은 중복된 패킷으로 간주하고 drop,
    이전에 성공적으로 수신한 패킷(시퀀스 번호 0)의 ACK을 다시 전송합니다.

  • ACK 패킷을 다시 보내는 이유는, 송신자가 수신 확인을 받지 못해 패킷을 재전송했을 가능성이 있기 때문(기다리다 오래 걸려 재전송 할 경우)
  1. 수신자는 Wait for 1 상태를 유지하며, 시퀀스 번호가 1인 패킷을 기다림

이렇게 하는 이유는
1. 피드백 패킷의 손상으로 인한 재전송과
2. 오류가 발생시 재전송을 구분하기 위함이다.

  • 피드백 패킷의 손상으로 인한 재전송일 경우 (수신자가 ACK 보냈지만 손상)
    • 송신자는 재전송
    • 중복된 패킷이 도착할 것이다. (송신자가 기다리는 시퀀스 넘버가 아닐것)
      -> 떄문에 drop을 해야함
    • 이전 ACK을 다시 송신.
1. 송신자가 시퀀스 번호 0을 가진 패킷을 보냄 → 수신자는 ACK 0을 송신. 그 후 1을 기다리는 상태로 전이
2. 하지만 ACK 0이 송신자에게 도착하지 않음(손상 또는 손실).
3. 송신자는 시퀀스 번호 0을 가진 데이터를 다시 전송.
4. 수신자는 중복된 시퀀스 번호 0을 보고 ACK 0을 다시 보냄.
5. 송신자는 ACK 0을 받고 시퀀스 번호 1로 넘어감.
  • 오류 발생 시 데이터 패킷의 재전송(NAK 응답을 받음)
    • 송신자 재전송
    • 기다리는 시퀀스가 맞으면 ACK
1. 송신자가 시퀀스 번호 1을 가진 패킷을 보냄 → 수신자가 해당 패킷을 손상된 상태로 수신.
2. 수신자는 NAK 또는 응답을 보내지 않음.
3. 송신자는 타임아웃이 발생해 시퀀스 번호 1을 가진 데이터를 다시 전송.
4. 수신자는 정상적인 시퀀스 번호 1 패킷을 받고 ACK 1을 송신.
5. 송신자는 ACK 1을 받고 다음 시퀀스 번호 0으로 넘어감.

문제

하지만 수신자는 발신자가 마지막 ACK/NAK을 받았는지 알 수 없다

수신자는 피드백패킷을 보내는데 잘 도착했는지 모른다.
-> 이 피드백패킷을 재전송 할 방법이 없음
-> 때문에 발신자는 동일 패킷을 재전송함 (중복패킷의 발생)
-> 3.0 의 타임아웃으로 해결


rdt 2.2

rdt 2.2이란?
1. data 전송시 에러 발생 가능
2. data 전송시 loss X 인 상황
3. 응답 피드백 패킷 손상 가능(loss 불가)
4. 전송 후 대기(stop-and-wait): 데이터를 주고 수신자의 피드백을 기다림
2.1 과 같은 기능을 하지만 NAK을 쓰지 않는다.

  • NAK의 문제점 해결
    RDT 2.1에서 NAK이 손상될 경우 패킷 재전송이 불가능해지는 문제를 해결하기 위해, 대신 중복 ACK을 사용해 수신자가 패킷을 잘못 받았음을 알림
    -> ACK, 0 / ACK, 1 를 피드백 패킷에 넣어 보낸다. (패킷의 순서 번호)


    1. ACK, 0 - 수신자가 시퀀스 번호가 0인 패킷을 정상적으로 수신했음을 알림
    2. ACK, 1 - 수신자가 시퀀스 번호가 1인 패킷을 정상적으로 수신했음을 알림

  • 단순화된 오류 처리
    수신자가 중복된 ACK을 보내는 것만으로 발신자가 패킷 재전송을 시작할 수 있기 때문에, 오류 처리 로직이 단순화됨

송신자

  • 중복 ACK를 받으면 NAK와 똑같이 동작
    -> 재전송

수신자

  • 패킷이 잘못 왔거나 손실이 일어나면, 이전에 보냈던 ACK 0,1 패킷을 보냄
    -> 자신이 받은 마지막 올바른 패킷이 0,1번 이라는 것을 알려주는 것이다.

1. 올바른 상황

1.	시퀀스 번호 0 패킷 전송:
	•	송신자가 시퀀스 번호 0인 패킷을 보냅니다.
	•	수신자가 이를 정상적으로 받으면, 수신자는 ACK 0을 송신자에게 보냅니다.
	•	송신자는 수신자로부터 ACK 0을 받으면, 패킷이 올바르게 전달되었다고 판단하고 다음 패킷(시퀀스 번호 1)을 보낼 준비를 합니다.
2.	시퀀스 번호 1 패킷 전송:
	•	송신자가 시퀀스 번호 1인 패킷을 보냅니다.
	•	수신자가 이를 정상적으로 받으면, 수신자는 ACK 1을 송신자에게 보냅니다.
	•	송신자는 수신자로부터 ACK 1을 받으면, 패킷이 올바르게 전달되었다고 판단하고 다음 전송을 위해 시퀀스 번호를 다시 0으로 전환합니다.

2. 송신자가 올바른 시퀀스의 패킷을 주었지만, 손실이 발생

1.	오류가 발생한 경우:
	•	예를 들어, 송신자가 시퀀스 번호 1의 패킷을 보냈지만, 중간에서 손실되었거나 수신자가 오류로 인해 이 패킷을 제대로 받지 못했다고 가정해 보겠습니다.
	•	수신자는 시퀀스 번호 1의 패킷을 기다리고 있었기 때문에, 이 패킷이 오지 않으면 문제가 발생합니다.
	•	수신자가 패킷을 받지 못했거나 손상된 패킷을 받았다면, 기대하던 패킷이 오지 않았음을 나타내기 위해 이전에 성공적으로 받았던 패킷에 대한 중복 ACK을 보냅니다.
2.	중복 ACK을 보내는 이유:
	•	송신자가 시퀀스 번호 1인 패킷을 보냈지만 수신자는 이를 제대로 받지 못했을 때, 수신자는 이전에 받았던 마지막 유효한 패킷에 대한 ACK 0을 다시 보냅니다. 이는 수신자가 아직 시퀀스 번호 1인 패킷을 받지 못했음을 나타내기 위한 것입니다.
	•	중복 ACK 0을 보내는 것은 “나는 아직 시퀀스 번호 0까지의 패킷을 받았고, 시퀀스 번호 1 패킷은 제대로 못 받았다”는 의미입니다. 따라서 송신자는 이 신호를 보고 시퀀스 번호 1 패킷을 다시 전송해야 함을 알게 됩니다.
3.	수신자가 시퀀스 번호를 기다리는 상태 전이:
	•	수신자가 시퀀스 번호 0인 패킷을 받으면 그 상태에서는 시퀀스 번호 1을 기대하게 됩니다.
	•	송신자가 시퀀스 번호 1인 패킷을 보냈으나 이 패킷이 손실되었을 경우, 수신자는 여전히 시퀀스 번호 1 패킷을 기다리고 있는 상태입니다. 이 상태에서 패킷이 손실되었다면, 수신자는 이전에 성공적으로 받은 패킷에 대한 ACK을 반복해서 송신자에게 보내 오류를 알리게 됩니다.
  • 수신자는 내가 마지막으로 받은 올바른 패킷이 0 번이야 하고
    1번 패킷을 정상적으로 받지 못했다 알림(ACK 0보냄)
  • 수신자의 ACK 1을 기다리고 있던 송신자는 중간에 패킷이 잘못되었구나 하고
    다시 1번 패킷을 재전송

3. 송신자가 수신자가 기다리는 시퀀스가 아닌 패킷을 전송(보낸걸 다시 보냈다)

보낸걸 다시 보낸이유는 수신자가 보낸 ACK 응답에 손실이 있어서 송신자가 재전송한 상황이기 때문이다.

1.	중복 패킷을 받은 경우:
	•	수신자가 시퀀스 번호 1 패킷을 정상적으로 받고, ACK 1을 보낸 후 시퀀스 번호 0을 기다리고 있다고 가정합니다.
	•	만약 송신자가 시퀀스 번호 1의 패킷을 다시 보내면, 수신자는 “이 패킷은 내가 이미 받은 패킷이다”라고 판단하게 됩니다.
	•	이 경우, 수신자는 중복된 패킷을 받았으므로 중복 ACK 1을 송신자에게 보내야 합니다. 이는 송신자에게 “나는 이미 이 패킷을 받았으니, 새로운 패킷을 보내라”는 신호가 됩니다.
  • 0번을 기다리는데, 1번 패킷이 온 경우
  • 나는 이미 이 패킷을 받았다고 송신자에게 알려줌 (ACK 1 보냄)
  • 수신자의 ACK 1을 기다리고 있던 송신자는 아무튼 중복이 일어났는지는 알 수 없지만, 수신자가 1번을 잘 받았으므로 0번을 주는 상태로 넘어간다.


rdt 3.0

rdt 3.0이란?
1. data 전송시 에러 발생 가능
2. data 전송시 loss가능 상황
3. ACK/NAK 패킷 손상가능 (loss도 가능)

하위채널이 패킷의 손실할 수 있다

다음과 같은 두 가지 부가 내용을 프로토콜이 다루어야 한다.

  1. 송신자는 어떻게 패킷 손실을 검출할 것인가?
  2. 패킷 손실이 발생했을 때 어떤 행동을 할 것인가?

수신자가 보낸 ACK신호가 loss발생하면 송신자는 하염없이 기다리게 된다.

즉, 송신자는 데이터 패킷이 손실되었는지, ACK가 손실되었는지, 패킷 또는 ACK가 단순히 지나치게 지연된 것인지를 알지 못한다.

만약 송신자가 패킷을 잃어버렸다고 확신할 정도로 충분한 시간을 기다릴 수만 있다면, 데이터 패킷은 간단하게 재전송될 수 있다.
-> 하지만 얼마동안이나 기다려야 할까?

  1. 길게 기다리게 되면, loss 발생을 정확하게 감지할 수 있지만 낭비가 크다
    -> 데이터 전송 성능안좋아짐
  2. 짧게 기다리면, 정확하지 않다
    -> 불필요 재전송 발생

송신자는 적어도

송신자와 수신자 사이의 왕복 시간 지연(중간 라우터에서의 버퍼링을 포함) + 수신 측에서 패킷을 처리하는 데 필요한 시간

시간 만큼을 기다려야 한다.

-> 이 시간 만큼 타이머를 두어 일정시간 오지 않는다면 재전송을 하자

송신자

  1. 매 패킷(첫 번째 또는 재전송 패킷)이 송신된 시간에 타이머를 시작한다.
  2. 타이머 인터럽트에 반응한다. (즉, 적당한 행동을 취함)
  3. 타이머를 멈춘다.

타이머 설정시간 내에 응답 패킷 도착한 상황

타이머 설정시간 내에 응답 패킷 도착하지 못한 상황

  • 오류가 나더라도 재전송 하지 않고 타이머가 만료되면 재전송을 한다.
    (이렇게 하는 이유는 수신자 응답 패킷이 늦게 도착한 경우를 무시하려고)

3.0의 액션

크게 네가지 상황으로 나눌 수 있다.

  1. loss가 없을 떄
    ➡️ 아주 잘 동작

  2. 전송패킷의 loss
    ➡️ 타임 아웃 후 재전송

  1. 응답패킷의 loss
    ➡️ 타임 아웃 후 재전송

  2. 응답패킷을 보냈지만 loss없이 늦게 도착한 경우
    ➡️ 타임 아웃 후 재전송
    ➡️ 수신자는 중복을 감지해야하고
    ➡️ 송신자는 수신자의 중복감지에 대한 ACK응답을 무시해야 함
    (ACK응답 받고 어플에서 데이터를 기다리는 상태인데 ACK응답패킷이 온다면 무시)

rdt3.0의 성능계산

송신자의 이용률(utilization) : 송신자가 실제 패킷을 보내느라 busy한 시간
이러한 이용률을 계산하여 성능을 분석한다.

rdt3.0의 성능이 별로인 이유

stop & wait 때문에 보낼 패킷이 남아 있어도 송신자의 ACK를 받아야지만 보낼수 있다.

전송률: 1Gbps
프로파게이션 딜레이: 15 ms
8000 bit 패킷 전송 시

-> 전송지연 = L / R = 8000bit / 1Gbps = 8 msec
  • 송신자가 패킷1개를 전송하는 과정에 걸리는 시간
    = 8 msec 시간 동안 패킷을 보내고 + 수신자의 ACK를 기다리고 받는 시간
    으로 이루어 진다
    = 8 msec + RTT (RTT는 프로파게이션딜레이 * 2 = 30)

송신자가 실제 데이터를 보내는데 바쁜시간 = 패킷 1개 전송시간 / (RTT + L/R)
= 0.00027

전체 시간 중 엄청 적은 시간만 실제로 패킷을 전송한다.
매우 적은 이용률을 갖는다.



파이프라이닝 프로토콜

stop & wait 때문에 성능이(적은이용률) 안나왔던 rdtx.x를 개선하기 위해
수신자의 응답을 기다리기 전에 패킷을 순차적으로 보내면서 이용률을 높이는 방식을 채택한다.

  • TCP에서 실제 사용하는 방식이다.

이러한 방식을 구현하기 위해 필요한 것 2가지

  1. 시퀀스 번호가 많이 필요하다
    (각 패킷에 대해 시퀀스 넘버를 붙여야 함)
  2. 버퍼가 필요하다.
    (송신자는 패킷이 잘 도착했는지 추적을 해야 하므로 버퍼를 사용)

파이프라이닝 성능 분석

  • 실제 보내는 패킷이 n 개 이면 1개 씩 보낼때와 비교해 n배의 이용률(성능)이 좋아진다.

GO-Back-N (GBN)

오류가 발생한 패킷 이후의 모든 패킷을 재전송

주요 구성 요소

  1. 슬라이딩 윈도우
    • 송신자가 한 번에 여러 패킷을 연속적으로 보낼 수 있게 함
    윈도우 크기(N): 송신자가 ACK(인증 응답)를 받지 않고 보낼 수 있는 최대 패킷의 수
    • 송신자는 ACK을 받은 패킷들은 윈도우에서 제거하고, 윈도우를 앞으로 슬라이딩하면서 다음 패킷을 전송할 수 있게 됨
  2. 시퀀스 번호
    각 패킷마다 고유한 시퀀스 번호가 붙어 있다.
    sned base: 보낸 패킷중 ACK를 못받은 가장 오래된 패킷
	예시로 이해하기:

	•	시퀀스 번호가 0에서 7까지 있다고 가정합니다.
	•	송신자는 패킷을 차례로 보내면서 시퀀스 번호를 붙입니다. 예를 들어, 0, 1, 2, 3, …, 7까지 보낸 후, 그다음 패킷은 시퀀스 번호 0으로 돌아갑니다.
	•	이때, 윈도우 크기가 시퀀스 번호의 절반 이하(예: 4 이하)로 설정되면, 송신자는 ACK 3을 받았을 때 그 시퀀스 번호가 이전 순환에서 온 것인지, 아니면 현재 순환에서 온 것인지 명확히 구분할 수 있습니다.
	즉, 시퀀스 번호가 순환하면서 사용되더라도, 윈도우 크기를 제한함으로써 송신자와 수신자는 어떤 패킷이 ACK를 받았는지 혼동하지 않게 됩니다.

	시퀀스 번호가 순환하는 과정:

	1.	송신자는 시퀀스 번호 0부터 시작해서 패킷을 보냅니다.
	2.	시퀀스 번호는 유한한 범위 내에서 0, 1, 2, …, N-1까지 증가합니다.
	3.	N에 도달하면 다시 0부터 시작해서 시퀀스 번호가 부여됩니다.
	4.	송신자와 수신자는 윈도우 크기 덕분에 이전 순환과 현재 순환의 시퀀스 번호를 구분할 수 있습니다.
  1. ACK(인증 응답)
    • 수신자가 정상적으로 패킷을 수신하면, 해당 패킷의 시퀀스 번호에 대한 ACK를 송신자에 send
    ➡️ 송신자는 ACK을 수신하면 해당 패킷이 정상적으로 수신되었음을 확인하고, 그 패킷을 더 이상 재전송할 필요가 없다는 것을 알게 된다.

    누적 ACK(cumulative)
    = ACK을 보낼 때, 그 패킷 이전의 모든 패킷도 정상적으로 수신되었음을 한 번에 확인
    ➡️ 수신자는 누적 ACK을 사용하여 가장 최근에까지 순서대로 받은 패킷에 대한 ACK를 보냄
    (송신자는 ACK 3 이 오면 1,2,3이 잘 갔다고 판단, 오류나 loss시 3번 패킷 이후부터 재전송)

  2. 타임아웃
    • 타이머는 윈도우에서 가장 먼저 전송된 패킷에 대해 설정하고,
    ACK응답을 받으면 그 패킷의 다음 시퀀스를 기준으로 타이머를 설정한다.
    • 타임아웃 시 ACK 받은 시퀀스 번호 보다 높은 패킷을 모두 전송한다.

  3. loss
    • 1,2,3,4 패킷을 전송하는데, 2번을 못받고 1,3,4만 받으면 2번부터 다시 다 보냄

때문에 GO-Back-N이라 불림

송신자

  • 수신자가 보낸 ACK에따라 윈도우를 이동
    (마지막 ACK가 3이였으면 base는 4가 되고, 오른쪽으로 이동한다)
  • 노란색 부분(보냈지만 아직 ACK 못받은 패킷)은 오류나 loss발생 시 재전송됨

수신자

  • 수신자는 가장 마지막으로 올바를 순서로 받은 패킷의 시퀀스 번호를 ACK에 와 같이 보낸다.
    ➡️ 때문에 중복 ACK가 발생할 수 있다
    (처음 전송에서 잘 받아서 ACK 3을 보냈는데 다음의 전송에서 4,5,6,7 패킷을 보낼 때 loss가 발생하면 다시 ACK 3을 보낸다)
  • rcv_base : 수신자가 다음으로 기대하는 패킷의 시퀀스 번호
  • out-of-order패킷은 일반적으로 drop한다.(빨간색 부분)
    하지만 버퍼링을 통해 가지고 있을 수도 있음(구현자 맘임)

액션

  • 이러한 동작은 상당한 낭비가 있다.
    3,4,5 패킷을 잘 받았지만 불필요하게 버리고 재전송 받아야 한다.
    ➡️ 손실된 하나의 패킷으로 인해 많은 패킷 재전송 필요하다.

Selective Repeat (SR)

오류가 발생한 패킷만 선택적으로 재전송

고백엔의 낭비를 해결하기 위해 다음과 같은 설정이 추가 되었다.

  • SR은 순서상관없이 개별패킷에 대해 ACK를 보낸다.
  • 각 패킷당 타이머가 필요하고, 타임아웃 시 해당 패킷(unACK패킷)만 재전송 가능하게 한다.

➡️ 때문에 수신자는 도착한 각 패킷당 정보를 저장하고 있어야 해서 버퍼가 필요하다.

주요 구성 요소

  • 슬라이딩 윈도우
    송수신자 모두 윈도우를 사용한다.
    ➡️ 송신자 - 윈도우 크기만큼의 패킷을 연속해서 보낼 수 있음
    ➡️ 수신자 - 버퍼를 사용해 윈도우 크기만큼의 패킷을 저장한다.

  • 개별 ACK
    개별적으로 패킷에 대해 ACK를 보낸다.

  • 오류 및 패킷 손실 처리
    SR에서는 수신자가 순서가 맞지 않는(out-of-order) 패킷을 받더라도 버퍼에 저장


그렇다면 SR은 어떻게 패킷의 순서를 보장할까?

  1. 우선 수신자는 순서에 맞지 않은 패킷이 도착하면 버퍼에 저장한다.

  2. 그 후 문제의 패킷의 타이머가 타임아웃으로 재전송되면 해당 패킷을 받아 ACK응답을 보낸다

  3. 따라서, 순서가 맞지 않는 패킷이 도착하더라도 버퍼에 저장해 두었다가, 손실된 패킷이 재전송되면 순서를 맞춰 상위 계층으로 전달한다.

  4. 버퍼를 비운다


송신자

  • 윈도우 안에 전송대기중인 시퀀스 번호가 있으면 패킷을 전송한다.

  • 노란색 패킷이 타임아웃이면 해당 패킷을 재전송한다

  • sendbase부터 + N 개 까지 다 초록색이면,(다 ACK응답을 받았다면)
    N번 패킷에 마킹을 하고 윈도우를 N다음으로 이동한다.

수신자

  • rcv_base ~ rcv_base + N - 1 패킷 수신 시
    (수신자가 기대하는 윈도우 내의 패킷을 수신했을 때)
    ➡️ 1. 잘 받은 패킷은 ACK를 보냄 (윈도우 내 범위에서 온 패킷을 잘 받으면 ACK)
    ➡️ 2. 순서가 안맞는 패킷은 버퍼에 저장
    (예를 들어, 수신자가 rcvbase = 2이고 패킷 4를 먼저 받았다면, 패킷 4는 버퍼에 저장)

  • rcvbase - N ~ rcvbase - 1 패킷 수신 시
    (이미 수신하여 ACK을 보낸 적이 있는 패킷)
    ➡️ 송신자가 ACK을 제대로 받지 못해 패킷을 재전송한 경우 수신할 수 있는 시퀀스 번호
    (수신자는 중복 ACK을 보내 송신자에게 해당 패킷이 이미 수신되었음을 다시 알림)

  • 수신 윈도우 범위 밖의 패킷이 도착
    ➡️ 무시

현재 상태:
	•	rcvbase = 2, 윈도우 크기 N = 4
	•	수신 가능한 시퀀스 번호 범위: [2, 5]

1.	패킷 4를 수신:
	•	패킷 4는 순서가 맞지 않지만, 수신 윈도우 안에 있으므로 버퍼에 저장하고, ACK 4를 보냅니다.
2.	패킷 2를 수신:
	•	패킷 2는 순서가 맞는 패킷이므로, 상위 계층에 전달하고, ACK 2를 보냅니다.
	•	버퍼를 확인하고, 버퍼에 저장된 패킷 3과 4도 순서대로 상위 계층에 전달합니다.
	•	rcvbase는 이제 5로 이동하여, 다음으로 기대하는 패킷이 됩니다.
3.	패킷 1을 재전송 받아 수신:
	•	패킷 1은 rcvbase - N 범위에 속하므로, 수신자는 ACK 1을 다시 보냅니다. 송신자가 중복 ACK을 받으면 더 이상 재전송하지 않습니다.

액션

SR의 딜레마

충분한 시퀀스 번호의 범위를 확보해야 한다,

  • SR에서는 송신자와 수신자 모두 각각 윈도우를 사용한다.

    1) 송신자의 윈도우: 동시에 전송할 수 있는 패킷의 개수를 나타냄
    2) 수신자의 윈도우: 순서대로 도착하지 않은 패킷을 버퍼링할 수 있는 개수를 나타냄

문제가 없는 경우

  • 응답패킷에 loss 가 없다면 잘 동작

문제 상황

  • 응답패킷에 loss 가 있다면 윈도우가 동기화 되지 않으며, 문제발생
  • 0번패킷을 잘 받았지만 송신자는 다시보내게된다.
  • 수신자는 이미 받은 패킷을 새로운패킷을 착각하게 된다.
만약 시퀀스 번호가 6까지 이면
위의 상황에서 윈도우가 3 5 6 을 가르키게 되고, 
송신자가 다시 보내는 0 1 2에 대해서는 중복 ACK를 보낸다.
추후 기다리는 패킷과 혼동이 일어나지 않음

시퀀스 번호의 범위 >= 2 × 윈도우 크기
를 만족해야 한다.


특징Go-Back-N (GBN)Selective Repeat (SR)
오류 처리 방식손실된 패킷 이후의 모든 패킷을 재전송손실된 패킷만 선택적으로 재전송
ACK 처리 방식누적 ACK 사용 (가장 최근에 순서대로 수신된 패킷에 대한 응답)개별 ACK 사용 (각 패킷마다 ACK 전송)
윈도우 크기 제한송신자와 수신자의 윈도우 크기가 동일수신자 윈도우 크기는 송신자 윈도우 크기와 독립적
수신자 동작순서가 맞지 않은 패킷은 버림순서가 맞지 않은 패킷도 버퍼링하여 저장
효율성손실 발생 시 불필요한 재전송이 많아 비효율적일 수 있음불필요한 재전송이 없고 더 효율적
구현 복잡도구현이 상대적으로 간단버퍼링과 개별적인 ACK 관리로 복잡
타이머 사용송신자는 하나의 타이머만 사용각 패킷마다 개별 타이머 설정 필요
시퀀스 번호 범위윈도우 크기보다 같거나 클 수 있음시퀀스 번호 범위는 윈도우 크기의 두 배 이상이어야 함
윈도우 이동 조건가장 오래된 패킷의 ACK을 받을 때 윈도우 이동순서에 맞는 패킷을 수신할 때마다 윈도우 이동
사용 예시데이터 손실이 적고 구현의 단순함이 필요한 경우데이터 손실이 많고 네트워크 자원의 효율적 사용이 중요한 경우
  • GBN단순한 구조로 쉽게 구현할 수 있지만, 패킷 손실이 발생하면 불필요한 재전송이 많아질 수 있다는 단점.
  • SR각 패킷마다 개별 ACK을 사용하고 버퍼링을 통해 순서가 맞지 않은 패킷도 관리하여 더 효율적이지만, 구현이 복잡.
profile
다 같이 화이팅! 🙋‍♂️

0개의 댓글