본문 바로가기
Computer Science/컴퓨터 네트워크

신뢰적인 데이터 전달 프로토콜의 구축

by Libi 2021. 7. 8.
반응형

이전에 TCP/IP 4계층 전송 계층에서 데이터를 전송하기 위해 사용되는 대표적인 프로토콜은 TCP, UDP가 있다고 하였다. TCP, UDP의 차이 중 하나는 신뢰적인 서비스를 제공해 주냐이다.

TCP는 신뢰적인 서비스를 제공해 주는 반면, UDP는 비신뢰적인 서비스를 제공해 준다. TCP, UDP를 배우기 앞서 최종적인 신뢰적인 데이터 전송 프로토콜(Reliable Data Transfer Protocol : rdt)이 어떠한 과정을 통해 구축되었는지 한 번 짚고 넘어가도록 하자.

 

완전한 신뢰적 데이터 전송 프로토콜에 도달하기 위해서는 총 4가지 단계를 거친다. 천천히 살펴보도록 하자. 단, 단방향 데이터 전송(Unidirectional Data Transfer)의 경우인 송신 측으로부터 수신 측까지의 데이터 전송만을 고려하겠다. 또한 송신자와 수신자에 대한 이해를 돕기 위해 유한 상태 머신(Finite State Machine : fsm)을 사용하겠다.

1. 완벽하게 신뢰적인 채널 상에서의 신뢰적인 데이터 전송 : rdt1.0

먼저, 하위 채널이 완전히 신뢰적인 가장 간단한 경우를 고려해보자.

송신 측

  • rdt_send(data) : 이벤트에 의해 상위 계층으로부터 데이터를 받아들인다.
  • packet=make_pkt(data) : 받아들인 데이터를 포함한 패킷을 생성한다.
  • udt_send(packet) : 생성된 패킷을 채널로 송신한다.

수신 측

  • rdt_rcv(packet) : 이벤트에 의해 하위의 채널로부터 패킷을 수신한다.
  • extract(packet, data) : 패킷으로부터 데이터를 추출한다.
  • deliver_data(data) : 추출한 데이터를 상위 계층으로 전달한다.

 

이러한 간단한 프로토콜에서는 데이터 단위와 패킷 단위의 차이점이 없다. 또한, 하위 채널에서 송신한 데이터는 완전히 신뢰적이기 때문에 오류가 생길 수 없으므로 상위 채널에서는 어떤 피드백도 제공할 필요가 없이 받아들이면 된다. 그리고 수신자는 송신자가 데이터를 송신하자마자 데이터를 수신할 수 있기 때문에 속도를 제어할 필요도 없다.

 

2. 비트 오류가 있는 채널 상에서의 신뢰적 데이터 전송 : rdt2.0

두 번째로 살펴볼 상황은 패킷 안의 비트들이 하위 채널에서 손상되는 상황이다. 이러한 오류들은 보통 패킷이 전송 또는 전파되거나 버퍼링 될 때 네트워크의 물리적 구성요소에서 일반적으로 발생한다. 전송된 모든 패킷들은 손실만 있으며 송신된 순서대로 수신된다고 가정하자.

이러한 상황은 어떻게 해결해야 할까? 간단하게 전화 통화를 예시로 들어보자.

우리는 전화 통화 중에 상대방의 메시지를 제대로 수신하였다면 "알겠습니다."와 같은 긍정 확인 응답(Positive Acknowledgment)을 보낼 것이며, 제대로 수신하지 못하였다면 "다시 한번 말씀해 주시겠어요?"와 같은 부정 확인 응답(Negative Acknowledgment)을 보내고 재전송을 요청할 것이다.

이처럼 비트 오류가 있는 채널에서는 재전송을 기반으로 하는 자동 재전송 요구(Automatic Repeat reQuest, ARQ) 프로토콜을 사용한다.

비트 오류를 처리하기 위해서 ARQ 프로토콜은 다음과 같은 기능을 가진다.

  • 오류 검출 : 체크섬 필드를 사용하여 비트 오류가 발생했을 때 수신자가 검출할 수 있도록 한다.
  • 수신자 피드백 : 패킷을 제대로 수신하였지를 판단하기 위해 송신자에게 ACK or NAK로 피드백한다.
  • 재전송 : 재전송 요청을 받았다면 송신자는 패킷을 다시 전송한다.

 

송신 측

  • 송신 측은 2개의 상태를 가진다.
  • rdt_send(data) : 이벤트에 의해 상위 계층으로부터 데이터를 받아들인다.
  • sndpkt=make(data, checksum) : 받아들인 데이터에 오류 검출을 위한 체크섬 필드를 포함한 패킷을 생성한다.
  • udt_send(sndpkt) : 생성된 패킷을 채널로 송신한다.
  • 패킷을 송신한 후에는 우측 상태로 넘어와 수신 측으로부터 ACK or NAK 응답을 기다린다.
  • 만약 ACK 피드백이 돌아온다면 좌측의 상태로 넘어가 상위 계층으로부터 데이터가 전달되기를 기다린다.
  • 만약 NAK 피드백이 돌아온다면 ACK 피드백이 돌아올 때까지 udt_send(sndpkt) : 재전송 과정을 반복한다.
  • 송신자가 ACK 또는 NAK를 기다리는 상태(우측 상태)에 있는 경우, 상위 계층으로부터 더 이상의 데이터를 전달받을 수 없다. 이를 전송-후-대기(Stop-and-Wait) 프로토콜이라고 한다.

수신 측

  • rdt_rcv(packet) : 이벤트에 의해 하위의 채널로부터 패킷을 수신한다.
  • corrupt(rcvpkt) : 수신한 패킷에 오류가 있다면 NAK, 없다면 ACK 피드백을 패킷에 포함한다.
  • extract(packet, data) : 패킷으로부터 데이터를 추출한다.
  • deliver_data(data) : 추출한 데이터를 상위 계층으로 전달한다.

 

프로토콜 rdt2.0은 잘 동작되는 것 같지만 실제로는 치명적인 결함이 있다. 바로 송신자가 수신자에게 보내는 ACK/NAK 피드백이 손상될 수 있다는 가능성을 고려하지 않은 것이다.

수신 측에서 송신 측으로 ACK 피드백을 보냈는데 중간에 ACK 패킷이 손상되어 송신 측이 제대로 알아듣지 못한다면 어떻게 해야 할까?

간단하게 송신 측에서 수신 측으로 다시 한번 data를 보내면 된다. 그럼 data에 대한 피드백이 다시 올 것이니깐. 하지만 수신 측은 이전에 받은 data를 잘 수신하였다고 ACK 피드백을 보냈는데 똑같은 data가 온다면 이게 과연 다음 data를 의미하는 것인지 중복으로 보낸 것인지 알 수가 없다.

이러한 문제점을 해결하기 위해 패킷에 순서 번호(Sequence Number)을 포함시키는 것이다.

3. ACK/NAK 피드백이 손상되는 채널 상에서의 신뢰적 데이터 전송 : rdt2.1, rdt2.2

세 번째로 ACK/NAK 피드백이 손상되는 상황이다. 이를 해결하기 위해 우리는 순서 번호를 추가한다고 하였다. 송신 측은 0과 1을 순서 번호로 사용하고, 수신 측은 이를 통해 수신한 패킷이 중복 패킷인지를 판단한다.

rdt2.1은 수신자로부터 송신자까지의 긍정 확인 응답과 부정 확인 응답을 모두 포함한다. 하지만 잘 생각해 보면 NAK를 송신하는 것 대신에, 가장 최근에 정확하게 수신된 패킷에 대해 ACK를 송신함으로써 NAK를 송신한 것과 같은 효과를 얻을 수 있다.

rdt2.2는 rdt2.1의 기능에서 NAK을 사용하지 않도록 개선하였다.

 

4. 비트 오류와 손실 있는 채널 상에서의 신뢰적 데이터 전송 : rdt3.0

마지막으로 살펴볼 상황은 비트 손상과 더불어 패킷을 손실하는 상황이다. 이를 해결하기 위해 고려해야 하는 것은 1. 어떻게 패킷 손실을 검출할 것인가?, 2. 패킷 손실이 발생했을 때 어떤 행동을 할 것인가?이다.

송신자의 입장에서는 패킷을 재전송하는 방법은 최고의 선택이다. 패킷이 손실되던지, ACK가 손실되던지, 패킷 또는 ACK가 단순히 지나치게 지연된 건지를 알 수가 없기 때문에 패킷을 재전송하면 이러한 모든 경우를 해결할 수 있다.

그렇다면 얼마 동안 기다린 후에 재전송을 해야 할까? 이를 위해 카운트다운 타이머(Countdown Timer)를 이용한다. 타이머를 통해 일정 시간이 지난다면 어떤 상황이든 상관없이 송신 측에서 패킷을 재전송하도록 한다.

 

b~d의 상황을 보면 패킷 손실, ACK 손실, 시간 지연에 상관없이 타임아웃이 발생했다고 판단되면 패킷을 재전송한다. c의 상황을 보면 패킷을 재전송했을 때 중복 데이터인지 판단해야 하는데 이는 순서 번호를 통해 충분히 해결 가능하다는 것을 이전 단계에서 확인하였다. 또한, 패킷의 순서 번호가 0과 1이 번갈아 일어나므로 프로토콜 rdt3.0은 얼터네이팅 비트 프로토콜(Alternating-Bit Protocol)이라고도 부른다.

지금까지 데이터 전송 프로토콜의 주요 구성요소를 정리해 봤다. 체크섬, 순서 번호, 타이머, ACK/NAK 등을 통해 우리는 완벽하게 신뢰적인 데이터 전송을 할 수 있도록 하였다.

하지만 아쉽게도 rdt3.0은 기능적으로 매우 정확한 프로토콜임에도 불구하고 오늘날의 고속 네트워크에서 만족스러운 성능을 보여주지 못한다는 단점이 있다.

그 이유는 전송-후-대기(Stop-and-Wait) 방식이기 때문이다. 다음 글에서 rdt3.0의 부족한 성능을 확인해보고 이를 개선한 2가지 방법을 소개하겠다.

반응형

댓글