받는 쪽에서 데이터가 유실되지 않고 전송됨
네트워크 계층은 unreliable channel
이지만 전송 계층에서는 reliable channel
처럼 보여야 한다.
단순한 RDT 프로토콜을 구성한다고 생각할 때, 하나의 데이터를 보내고 목적지에 정확하게 도착했을 때만 다음 데이터를 보낸다고 생각해보자
RDT를 위해서는 네트워크 계층에서 발생할 수 있는 문제를 해결하면 될 것이다.
아래 사항들이 header에 들어가야할 것이다.
packet error
Error 감지 (checksum)
Feeback
sequence numbering
=> ACK / NAK이 제대로 전송되지 않을 경우 ?
sender가 제대로된 피드백을 받지 못해서 재전송 할 경우 receiver에서는 이게 재 전송된 데이터인지 전에 받은 데이터인지 구분할 필요가 있다.
이를 위해서 sender는 sequence number
를 보내서 새로운 메시지인지 중복된 메시지인지 트랙킹할 수 있도록 한다.
receiver는 중복에 상관 없이 피드백은 항상 보낸다.
단순한 RDT의 경우 한 개씩 제대로 보냈는지 확인하고 다시 보내기 때문에 1 bit만 있어도 충분할 것임
Nak-free : ack만 이용해서 성공했을 경우 ack와 다음으로 받을 시퀀스 넘버를 돌려 보냄
packet error, Loss 가 발생하는 경우
Loss 란 보내는 상황에서 패킷이 유실되거나 피드백이 유실되거나의 상황이다. sender 입장에서는 둘 다 똑같다. 둘 다 어차피 피드백이 안 오기 때문에 ..
실제 TCP는 데이터를 한번에 여러개 보내고 sender와 receiver가 정해지지 않는 등 더욱 복잡함
point - to - point
소켓과 소켓이 1:1 관계
Reliable, in-order byte stream
메시지가 유실되지 않고
메시지가 내려온 순서대로 전송됨
pipelined
한 꺼번에 메시지 여러개를 보냄
full duplex data
sender와 receiver가 정해진 게 아님
sender가 receiver가 될 수도 있음
Connection-oriented
Flow controlled
상대방 머신의 성능 에 맞게 보내는 속도를 조절해줌
congestion control
TCP는 byte 단위로 시퀀스 넘버를 붙인다. 각 세그먼트의 바이트 중에서 가장 첫 번째 바이트의 시퀀스 넘버가 그 세그먼트의 시퀀스 넘버가 됨
[ ] [ ] [ ]
byte 250 150 100
seq 250 100 0
Ack #100 일 경우 99번까지 완벽하게 받았고 100번을 기다린다는 뜻
갔다가 오는 시간에 마진을 붙이면 넉넉할 것이다. ( RTT + margin )
이를 위해서 매번 세그먼트를 보내고 피드백을 받을 때 마다 sample rtt를 측정한다.
sample rtt
: 세그먼트를 나갈 때 시간부터 피드백이 올 때까지 시간을 측정. 재전송한 세그먼트는 포함하지 않음
sample rtt는 라우터의 큐잉 상태에 따라 변화 무쌍하므로 평균 트렌드를 구함
매번 sample rtt를 측정할 때마다 최근 측정한 것이 가중치가 높게 적용되도록 estimatedRTT를 매번 갱신함
EstimatedRTT : (1 - a ) * EstimatedRTT + a * SampleRTT
따라서 TimeoutInterval = EstimatedRTT + 4 * DevRTT
로 정할 수 있다.
즉 타이머의 시간은 매번 갱신 되기 때문에 유연하게 적용될 수 있다.
각 소켓 쌍 마다 send buffer, receive buffer가 존재한다.
애플리케이션 프로세스가 소켓을 통해서 하위 계층으로 전송하는 속도와 실제 TCP에서 전송하는 속도가 다르기 때문에 그 차이를 처리하기 위해서 send buffer가 필요하다.
애플리케이션 프로세스에서 온 메시지는 send buffer
에 담긴다.
TCP는 window size
만큼만 한꺼번에 메시지를 보낼 수 있는데, 예를 들어 1000byte인 경우 0부터 999번까지만 처음에 나갈 수 있다. 이 세그먼트들은 다른쪽의 receive buffer
로 들어가게 된다.
receive buffer
에서는 받은 세그먼트를 저장해놓고 ack
를 보낸다. 제대로 도착했을 경우 해당 세그먼트를 애플리케이션 계층의 R/W에 맞춰서 올려보낸다.
send buffer
에서는 ack
를 확인하고 제대로 전송 됐을 경우 timer
와 sender base
를 제대로 전송된 시퀀스 번호 만큼 다음으로 이동시킨다. 윈도우 크기 만큼 이동하는 것이기 때문에 남는 크기 만큼 다시 segment
를 보낼 수 있다.
세그먼트가 유실될 경우 receive buffer
는 해당 순서의 ack
을 계속 보낸다. send buffer
에서는 타이머가 울리면 해당하는 세그먼트를 재 전송한다. 해당 순서의 세그먼트가 제대로 왔을 때만 어플리케이션 계층으로 보낸다.
즉,
send buffer
: 재전송을 위한 bufferreceive buffer
: in-order를 위한 buffer실제로는 send buffer가 동작하는 동시에 receive buffer도 따로 동작한다.
타이머가 터지기 전에 유실을 빨리 판단할 수 있는 방법이 있을까?
중복된 ACK가 3번 들어왔을 때 (실제로는 4번) 유실로 판단하고 전송하는 방법이 있다.
참고
http://www.kocw.net/home/search/kemView.do?kemId=1312397
http://www.kocw.net/home/cview.do?mty=p&kemId=1169634