[Network] Transport Layer

0. Transport Layer

전송 계층은 다양한 호스트들에서 동작하는 어플리케이션 응용 프로세스 간의 논리적인 통신을 제공한다. 3계층인 네트워크도 통신에 관한 계층인데, 네트워크 계층과의 가장 큰 차이는 'process to process'라는 것이다. 즉 네트워크 계층에서는 호스트간의 통신을, 전송계층에서는 프로세스간의 통신을 관리한다. 전송 계층에서는 오류가 발생하면 데이터의 재전송을 요청하여 신뢰할 수 있는(reliable) 통신이 가능하도록 한다.

 

프로토콜은 모두 end system에서 동작한다. 코어의 router들은 전송계층의 프로토콜을 구현하고 있지 않다. sender는 세그먼트 단위로 어플리케이션 계층의 메세지들을 잘라서 전송계층의 헤더를 붙이고 네트워크 계층으로 보내고, receiver는 세그먼트들을 합쳐서 메세지를 만들어 애플리케이션 계층으로 전송한다.

 

 

 

1. Multiplexing/Demultiplexing

전송 계층에서는 소켓들을 port번호에 따라서 분배한다. 하나의 애플리케이션에서도 여러 프로그램이 돌아가고, 하나 이상의 소켓을 생성하기 때문에 받은 소켓들을 포트번호를 이용해서 분배하는 과정을 Demultiplexing이라고 하고, 반대로 전송할 다양한 소켓들을 하나의 공유하는 네트워크 계층을 통해서 전송하는 과정을 Multiplexing이라고 한다.

 

 

 

송신측에서는 여러 소켓에서 데이터를 받아서 헤더를 구성하는데, 소켓마다 각기 다른 포트번호를 할당하여 공유하는 네트워크를 통해서 전송한다. 이 과정을 Multiplexing이라고 하고, 그러면 수신측에서는 하나의 ip로 들어온 패킷을 올바른 소켓에 집어넣는데 이러한 과정을 DeMultiplexing이라고 한다. 

 

TCP/UDP segment format

 

전송 계층에서는 이렇게 메세지나 세그먼트를 source port와 destination port에 따라서 분리/조립하고, 그 방법에 따라 TCP와 UDP 세그먼트로 분류한다.

 

 

 

2. Reliable data transfer (RDT)

rdt는 신뢰성 있는 데이터 전송을 위해서 사용된다. 전송계층의 하위 계층(네트워크 계층~)에서는 신뢰성을 보장할 수 없기 때문에 전송 계층에서 rdt를 이용하여 신뢰성을 보장해준다.

 

 

- 송신

상위 계층에서 보내려는 데이터가 있다면 rdt_send()를 통해서 데이터를 rdt 프로토콜로 전송하고, rdt 프로토콜에서 하위 레이어로 보낼 때 udt_send()를 통해 패킷을 전송한다.

- 수신

하위 레이어에서 받은 패킷을 rdt_rcv()를 통해서 rdt 프로토콜로 전송하고, rdt프로토콜에서는 deliver_data()를 이용해서 데이터를 상위 레이어로 전송한다.

 

 

rdt 1.0

: 신뢰할 수 있는 채널이라는 가정 하의 전송

rdt 1.0은 채널이 안정적이라는 가정 아래에 만들어졌다. (bit error나 packet loss가 발생하지 않음) 따라서 에러 검출과 복구에 대한 고려가 이루어지지 않는다.

 

 

송신측에서는 위에서 내려오는 reliable한 데이터를 단순히 패킷을 만들어서 밑으로 보내주고, 수신측에서는 하위 계층에서 올라오는 reliable한 데이터를 패킷을 추출하여 상위 계층으로 보낸다. 다만 데이터의 손실이 고려되지 않은 모델이므로 실제 활용에는 부적합하다.

 

 

rdt 2.0

: bit error만을 고려한 전송

2.0은 패킷에서의 bit error(bit flip)이 발생할 수 있음을 가정하고 만들어졌다. 따라서 이때의 에러 처리를 위해서 ACKs와 NAKs를 이용하여 수신자가 송신자에게 에러가 발생하였는지 여부를 추가적으로 전송해준다.

 

 

rdt 2.0의 경우 NAK신호를 통해서 에러 발생을 감지할 수 있고, 재전송을 요구한다. 다만 rdt 2.0은 송신자가 수신측에서 보낸 ACK/NAK신호를 모종의 이유로 받지 못해서 신호가 손실될 수 있다. 이럴 경우에는 수신측에서 무한정으로 ACK/NAK신호를 기다리게 될 수도 있다. 또한 에러가 발생하지 않았지만 NAK가 잘못 전송되어 중복된 패킷을 다시 받는 상태가 될 수도 있다.

 

 

rdt 2.1, 2.2

: ACK/NAK의 중복 처리 - seq#의 추가

2.1에서는 seq#(sequence number)를 추가하여 중복 처리문제를 해결했다. 송신 측은 ACK/NAK이 손실되었는지 알 수 있는 정보인 seq#를 패킷에 추가한 뒤에 전송하여 이를 해결한다. 다만 seq#은 ACK/NAK의 중복 전송 여부만 체크하기 위해서 만들어졌으므로 0,1의 두가지 상태만 존재하면 된다.

 

sender

 

receiver

 

송신 측에서 패킷과 함께 seq#0을 보냈다고 가정하자. 이때 ACK 0신호가 되돌아왔다면 다음에는 패킷과 함께 seq#1을 보내고, NAK 0이 되돌아왔다면 이전의 전송이 실패했다는 이야기이므로 이전 패킷과 함께 seq#0을 다시 전송한다.

수신 측에서는 단순히 들어온 seq#를 그대로 ACK나 NAK과 함께 돌려주면 된다.

 

2.2는 2.1에서 NAK신호를 제거한 버전이다. 원래는 수신 측에서 받은 seq#과 동일한 NAK을 보냈다면, 2.2에서 수신 측에서 NAK신호를 보내기 위해서는 이전에 받았던 seq#과 함께 ACK을 보낸다. 그러면 송신 측에서는 송신한 번호와 다른 seq#를 받게 되므로 오류가 발생했다는 사실을 알고 이전에 보낸 패킷을 재전송한다.

 

2.1과 2.2 모두 각각 NAK과 cumulative ACK을 통해서 에러 발생을 감지할 수 있으며, 재전송을 요청하게 된다. 하지만 이 역시 중간에 신호가 손실될 가능성이 여전히 존재한다.

 

 

rdt 3.0

: ACK/NAK의 손실(loss) 처리 - timer 추가 (stop and wait operation)

rdt 2.2버전까지는 패킷 에러 감지하고 재전송을 요청할 수 있으나 패킷이 중간에 유실되는 것은 대응할 수 없다. 그래서 rdt 3.0에서는 송신 이후 ACK신호를 'reasonable'한 시간동안 기다리고, 그 시간 이후에도 ACK가 오지 않으면 재전송한다. 따라서 추가적으로 timer를 필요로 한다.

 

sender

 

receiver

 

다만 패킷이 중간에 유실된 케이스가 아니라, 단순히 트래픽 등으로 인해 패킷의 전송이 늦어진 경우에는 중복된 패킷을 보내게 되어 순서가 꼬이는 등의 문제가 발생한다. 추가적으로 rdt 3.0까지도 패킷을 하나씩 전송하는 방식으로 이루어지므로 성능상의 문제가 발생한다.

 

 

 

3. Pipelined protocols

rdt 3.0에도 해결하지 못한 효율성과 시간 측면의 문제를 해결하기 위해서 pipelining protocol을 사용하게 된다. pipelining의 가장 큰 특징은 송신자가 다수의 패킷을 한 번에 보낸다는 점이다. 이 때 수신자가 유실이나 중복 등으로 문제가 발생한 패킷들을 처리하는 방법에 따라서 Go-back N과 Selective Repeat의 방법으로 나뉜다.

 

Go-back N (GBN)

송신자는 ACK이 아직 오지 않은 패킷을 N개까지 보낼 수 있다고 설정하면, size N의 버퍼를 만들어 그 버퍼의 크기만큼 패킷을 저장하여 전송한다. 

 

GBN buffer

 

send_base : 버퍼의 시작점. 이전의 패킷들은 모두 ACK을 받은 상태이다.

N : window size. 한번에 보낼 수 있는 버퍼의 크기이다.

nextSeqNum : 아직 보낸 적 없는 패킷

 

버퍼는 send_base에 위치한 패킷이 ACK되어야 sliding되는데. 이 때 버퍼의 움직임이 창문과 같다고 'sliding window'라고 부르기도 한다.

 

만약 패킷의 송신 과정, 혹은 ACK신호가 돌아오는 과정에서 하나라도 유실된다면 송신 측에서는 수신 측의 해당 seq#의 ACK신호를 받을 수 없게 된다. 결국 신호를 받지 못해 timeout이 발생한다면 송신 측에서는 이후에 들어오는 모든 패킷들의 ACK신호를 무시하고 timeout이 발생한 패킷을 다시 전송하는 방식으로 작동한다. 

 

GBN방식은 pipelining방식을 이용하여 rdt 3.0의 비효율성을 개선하였으나, 패킷의 손상이나 유실이 발생한다면 그 패킷 이후에 들어오는 패킷들에 대해서도 모두 손해를 보기 때문에 Selective Repeat이라는 방식이 만들어지게 된다.

 

 

Selective Repeat

 GBN과 가장 큰 차이는 각 패킷마다 timer를 설정하여 timeout을 각각 계산하며, 각각에 대한 관리가 이루어지므로 GBN처럼 버퍼 모두를 재전송해야하는 일이 발생하지 않으며, ACK신호를 받지 못한 것들만 재전송한다는 점과, 수신 측도 버퍼를 가지고 있어서 패킷이 도착하면 바로 상위 계층으로 전달하지 않고 일단 버퍼에 저장한 후, 이전 패킷들이 연속적으로 모두 ACK된 패킷만 상위 계층으로 전달한다는 점이다.

 

이상태로 rcv_base 패킷이 도착하면 3개의 패킷이 상위계층으로 전달된다

 

다만 selective repeat의 경우 버퍼의 모든 패킷에 대해 timer가 존재해야 하므로 overhead가 발생하고, ACK신호가 누락될 경우 송신측에서 재전송하는 패킷을 새로운 패킷이라고 간주하고 받아서 중복된 패킷을 받을 수도 있다. 따라서 버퍼의 크기를 seq#의 크기의 절반 이하로 설정해주어야 한다.

'[ CS기초 ] > 네트워크' 카테고리의 다른 글

[Network] Network Layer  (0) 2022.03.04
[Network] UDP, TCP  (0) 2022.02.15
[Network] 웹과 HTTP  (0) 2022.02.08
[Network] HTTP 쿠키와 세션  (0) 2022.02.03
[Network] Application Layer - 소켓, 프로토콜과 DNS  (0) 2022.02.01