※kocw에서 제공하는 이석복 교수님의 컴퓨터네트워크 수업을 듣고 필기한 내용입니다.
출처를 따로 밝히지 않는 한 전부 해당 수업에서 제공한 자료들이며 제가 작성한 부분에 있어 틀린 부분이 있을 수도 있다는 점 양해바랍니다.
Reliable Data Transfer(RDT) 프로토콜
- 기본적으로 tcp는 udp보다 더 많은 것을 제공하는데, 그 중 첫번째는 tcp는 reliable한 데이터를 제공함
- 전송계층 밑에 계층에서 이루어지는 전송은 reliable 하지 않음(Message error, Message loss가 있을 수 있음)
- 전송계층에서 메세지 에러와 유실을 체크해줘야됨
그럼 reliable을 보장하는 Reliable Data Transfer(RDT) 프로토콜을 한번 간단한것부터 점진적으로 개발시켜보자
RDT v1.0: 전송되는 모든 데이터가 에러없고 유실 없음
- sender: 데이터 전송만 하면됨
- receiver: 데이터 받기만 하면됨
RDT v2.0: 전송되는 데이터가 에러가 생길수 있으나 유실은 없음
- 3가지 기능이 추가되야됨
1. Error detection - add checksum bits 패킷 헤더에 체크섬비트를 추가해서 에러 체크를 해야됨
2. Feedback - 리시버가 에러없는 패킷을 받으면 ACKs(Acknowledgements)를, 에러있는 패킷을 받으면 NAKs(Negative acknowledgements)를 센더에게 전송
3. Retransmission - NAK을 받으면 방금 보낸 패킷 재전송
- 센더 패킷 보냄 -> 리시버 받아서 ack나 nak을 보냄 -> 센더가 nak을 받으면 재전송, ack를 받으면 다음 패킷 전송
RDT v2.1: 만약 리시버에서 보낸 ACK or NAK가 에러가 생기면?
- 센더가 ack를 받았는지 nak을 받았는지 모르므로 일단 무조건 재전송함
- 그럴경우 리시버가 이게 새로운 패킷인지 아님 센더가 ack를 못받아서 재전송한건지 모름
- 헤더에 Sequence number를 추가(처음 보낸건 0, 그다음은 1, 그다음은 0.... 이렇게 하면 0,1 만 추가해도 됨)
- 리시버는 시퀀스넘버를 확인 후 순서에 맞으면 받고 순서에 맞지 않으면 버림(중복된거 제거 Reveiver discards duplicate packet)
sender:
1. seq num added to pkt
2. must check if reveibed ACK/NAK corrupted
3. Retransmit on NAK or corrupted feedback
receiver:
1. must check if reveived packet is duplicate
2. send NAK if reveived packet is corrupted, send ACK otherwise
RDT v2.2: NAK을 없애고 ACK만으로 동작하게 함
- 리시버는 무조건 ACK만을 보냄
- 만약 에러난 포켓을 받았을 경우 ACK를 보내되 같은 시퀀스 번호로 보냄
- 센더는 받은 시퀀스 번호로 다음 포켓을 보낼지 아님 재전송할지 결정함
- 즉, 시퀀스번호 만으로 ACK or NAK을 판단
RDT v3.0: 전송되는 데이터가 에러, 유실 둘다 발생할 수 있음(실제상황)
- 데이터 유실이 발생될 경우, 어느 정도 경과 시간이 지난 후 재전송해야됨
- 이때 Timer가 필요함
- 센더는 "reasonable"한 기간동안 ACK를 기다린 후 재전송 해야됨
- 이때 타이머가 너무 빠를시
장점: 데이터 유실이 발생할 시 빠르게 복구 가능함
단점: 유실이 발생하지 않고 단지 느리게 도착해도 재전송 할수 있음(네트워크 과부화)
- 타이머가 너무 느릴시
장점: 네트워크 과부화를 줄일 수 있음
단점: 데이터 유실 발생 시 복구가 느림
그래서 항상 타이머 시간을 어떻게 "reasonable" 하게 잡아야됨
- 지금까지의 RDT로 reliable한 데이터 전송을 보장할 수 있음, 하지만 한번에 하나의 패킷만 전송하고, ACK가 올때까지 아무것도 안하고 있는 등 비효율적인 면이 있음
- 실제로는 한꺼번에 여러개의 패킷을 보내는 구조로 되어있음(파이프라인)
- 파이프라인으로 보내는 방법 2가지:
1. go-Back-N
2. Selective repeat
(이 둘은 실존하는 프로토콜은 아니나, TCP가 이 방법들과 유사하게 사용되고 있음)
GBN (Go-Back-N)
- GBN 방식은 한번에 다수의 패킷을 버퍼에 담아놓고 전송함
- 버퍼의 크기를 window size라고 함, window size 만큼은 피드백을 받지 않고 보내기만함
- GBN 에서 ack는 쌓는형식("ACK11" 은 11번 패킷까지 잘 받았다, 12번 패킷 보내라)
- ACK를 받으면 해당 패킷을 윈도우에서 제거하고 새로운 패킷을 윈도우에 집어 넣음
- 이때 오류나 유실로 패킷 타임아웃이 되면 윈도우의 처음부터 재전송(win size = n일때 오류나 유실로 타임아웃이 되면 n만큼 돌아간다고 해서 go back n)
- ex)
n=4일때 4만큼의 데이터를 한꺼번에 보내고(0,1,2,3), ack0을 받으면 윈도우에서 0을 삭제하고 4를 추가(1,2,3,4) 패킷 1이 타임 아웃되면 다시 1,2,3,4 전송, ack1받으면 윈도우에서 1삭제 5추가(2,3,4,5).....
- 오류,유실 발생시 윈도우 크기만큼 재전송 하는 이유는 receiver가 받은 패킷을 저장할 버퍼를 가지고 있지 않고 자신이 받아야할 시퀀스 넘버만 기다리는 기능만 가지고 있어서 그럼
- 그래서 GBN의 단점은 단 하나의 패킷이 유실되도 윈도우 전체를 재전송 해야한다는것, 실제로는 윈도우 사이즈가 수천개에 다다를텐데 그러면 낭비가 심해짐
Selective repeat
- GBN의 단점을 해결하기 위해 나옴, 리시버가 받은 패킷을 임시 저장할 수 있는 버퍼를 가지고 있음
- 리시버는 순서에 맞게 들어온 패킷이 아니면 일단 버퍼에 저장
- 버퍼에 계속 담아두다가 센더가 재전송한걸 받으면 버퍼안에있는 모든 패킷을 어플리케이션에 올리고 ACK 보냄
- 여기서 문제가 될수 있는 점은 시퀀스 넘버가 패킷 갯수만큼 커질 수 있다는점(전송할 실제 데이터가 아닌 헤더에 들어가는 내용은 최대한 최소화해야됨)
해결방법:
- 최소한의 시퀀스넘버를 잡고, 그걸 반복해서 사용한다(0,1,2,3,01,2,3,....)
- 시퀀스 넘버를 너무 작게 잡으면, 패킷은 잘갔는데 ACK가 유실될 경우 센더가 재전송했는데 리시버가 그걸 재전송된게 아니라 다음 패킷인줄 알게됨
- 적당한건 win size X 2정도, 그쯤 어딘가
여전히 해결해야 할 문제:
- 윈도우 안에 있는 각각의 패킷마다 타이머가 있다는 것
- 실제로 전송할땐 프로세스도 수십개에 각 윈도우 사이즈가 수천개씩 될텐데, 전부 타이머가 있으면 CPU가 버티지 못함
TCP는 이 문제를 해결하고자 윈도우 안에 대표 타이머 하나만 두고, 리시버도 대표 ACK 하나만을 보냄
'[CS] > [컴퓨터네트워크]' 카테고리의 다른 글
중간복습 - Network, Application layer, Transport layer (0) | 2021.03.15 |
---|---|
전송계층3 - TCP Protocol (0) | 2021.03.11 |
전송계층1 - 전송계층이 제공하는 2가지 기본 기능(Multiplexing and Demultiplexing, 에러체크) (0) | 2021.02.28 |
애플리케이션계층2 - 소켓프로그래밍 (0) | 2021.02.20 |
애플리케이션계층1 - 사용자계층 네트워크애플리케이션종류 (0) | 2021.02.16 |