전송 계층(3) - TCP(2)

이정인·2022년 3월 2일
1

컴퓨터 네트워크

목록 보기
5/11

TCP flow control

어플리케이션에서 리드 콜이 있으면 리시브 버퍼에서 어플리케이션으로 올려보낸다.

애플리케이션이 리드 콜을 하는 속도는 애플리케이션 계층에 달려 있기 때문에, send buffer에서는 receiver가 read하는 속도를 고려해야한다.

이를 위해서는 receive buffer에 남아 있는 공간을 Receive window라고 표현하며 이를 sender 측의 send buffer 쪽으로 보내주면 된다. 이는 TCP 헤더에 receive window에 적힌다. 즉 피드백이든 데이터 든 TCP에서 보내는 세그먼트에는 자기 자신의 receive window 사이즈가 적힌다. send buffer의 window 또한 receive window 사이즈에 의존적이게된다.

즉 상대방이 받을 수 있는 능력에 따라 보내는 속도를 조절하는 것을 흐름 제어 (flow control)이라고 한다.

코너 케이스

만약 rcv buffer가 가득 찼다가 공간이 생길 경우 언제 세그먼트를 보내야할까? rwnd가 0으로 왔을 경우 보내는 쪽 send buffer에서는 더 이상 세그먼트를 보내지 않을 것이다. 만약 자기 자신의 send buffer가 세그먼트를 보낼 때에 의존하는데, send buffer가 비어 있다면 데드락 상황에 빠지게 된다. 이러한 상황을 해결하기 위한 방법으로 만약 상대방이 rwnd 사이즈가 0이라고 보내왔으면 주기적으로 작은 세그먼트를 보내 보는 방법 있다. 실제 보내고자 하는 데이터에서 한 바이트만 가져다가 세그먼트에 넣어 (헤더: 40 + 데이터: 1) probe 패킷을 만들어 보내 보는 것이다. 만약 공간이 생길 경우 유의미한 ack을 받을 수 있다.

세그먼트의 크기 정하기 Nagle's algorithm : Sender

세그먼트의 크기는 작은데 데이터의 크기가 작다면 어떻게 보내야할까?

첫번째 세그먼트는 데이터의 양과 상관 없이 무조건 내보낸다. 피드백이 올 때까지 축적된 데이터 양이 세그먼트 최대 크기에 도달 했다면 피드백이 도착하기 전에 보내고, 아니라면 그냥 그만큼만 보낸다.

피드백이 도착하기 전까지 데이터양이 축적되어 있다면 기다릴 가치가 있기 때문이다.

애플리케이션이 메시지를 내려보내는 속도가 네트워크 상황이 더 빠를 경우 세그먼트의 사이즈가 커지게 되고, 애플리케이션의 속도보다 네트워크 상황이 더 빠를 경우 세그먼트 사이즈가 작아진다. 오버헤드가 많이 늘어나도 네트워크 상황이 좋아서 빠르게 보낼 수 있기 때문에 많이 보낼 수 있다.

Receiver의 동작 최적화

Clark's solution

rcv buffer의 사이즈의 빈 공간이 세그먼트 사이즈보다 더 작게 남았을 경우 아예 rwnd 사이즈를 0으로 해서 보내라

delayed ack

세그먼트를 받았을 때 해당 ack을 500ms 기다렸다가 보내보자. 만약 다른 세그먼트가 그 전에 도착한다면 한번에 ack를 보낼 수 있다.

Connection managment

TCP는 3-way handshake를 통해서 양쪽이 TCP connection을 맺었음을 agreement한다.

  • 클라이언트가 TCP SYN을 보낸다.

    TCP SYN은 데이터 없이 TCP segment의 header 부분만 채워져서 나간다. tcp syn bit가 1로 세팅되고 자기 자신의 최초의 시퀀스 넘버가 채워진다. 기본적인 정보 교환을 위한 메시지 이다.

  • 서버에서는 응답으로 SYN ACK를 보낸다.

    SYNbit = 1, seq= y , ACKbit = 1; ACKnum = x+ 1

    TCP segment의 header 부분만 채워져서 나간다.

  • 클라이언트에 TCP 자료구조가 생성이 되고 완료됐다는 ACK 메시지를 보낸다.

    ACKbit = 1, ACKnum = y + 1

    일반적인 ACK 메시지이기 때문에 실제로 보내고자 하는 메시지를 데이터에 담아서 보낼 수 있다. 즉 헤더와 데이터가 채워져서 나간다.

TCP: closing a connection

다 데이터를 주고 받았다면 모든 자료구조를 해제 시켜야한다.

  • 애플리케이션에서 클로즈 콜이 오면 클라이언트는 FIN 메시지를 보낸다.

    FINbit = 1, seq = x

  • 이에 대한 응답으로 서버는 ACK 메시지를 보낸다.

    ACKbit = 1; ACKnum = x+ 1

  • 서버에서도 FIN 메시지를 보낸다.

    FINbit = 1, seq = y

  • 이에 대한 응답으로 클라이언트는 ACK 메시지를 보낸다.

    ACKbit = 1; ACKnum = x+ 1

    이때 클라이언트는 바로 자료구조를 없애는 것이 아니라 ACK이 유실될 상황에 대하여 TIMED_WAIT 시간을 가진다.

TCP 혼잡 제어 (congestion control)

네트워크 상황에 맞춰서 보내는 양을 조절해주는 것

네트워크가 처리할 수 있는 양보다 더 많은 양의 데이터가 보내졌을 때 생기는 현상을 congestion이라고 한다.

큐의 크기가 제한되어 있고 재전송이 있다고 생각해보자

어플리케이션에서 보내는 양보다 TCP에서 보내는 양이 더 많을 것이다.

해결 시나리오 가정

  • 라우터에 빈 공간이 있을 때만 보낸다면 ?

    패킷 로스가 없을 것이다.

    하지만 라우터 큐에 빈 공간이 있는지 없는지 모르므로 비현실적이다.

  • 패킷이 유실 됐을 때만 재전송한다면?

    실제로 보내야할 양보다 많이 보내게 된다.

많이 보내서 막혔는데 해결하기 위해서 더 많이 보내게 된다

많이 보낼 수록 더 적게 받게 된다.

TCP는 피드백에 근거해서 현재 네트워크 상태를 추측해서 동작하게 된다.

Additive increases

send buffer에 영향을 미치는 두가지는 rcv window와 congestion window 이다. congestion window란 보내는 쪽에서 판단할 때 현재 네트워크가 받아 들일 수 있는 양을 말한다. send buffer의 크기는 둘 중에 작은 값으로 결정된다.

따라서 congestion window가 어떻게 변하는가가 congestion control의 핵심이다.

세그먼트를 보내고 그에 대한 피드백을 제대로 받으면 그만큼 congestion window의 크기를 늘린다. 보통 세그먼트는 maximum segment size로 정해져 있기 때문에 congestion window는 MSS 만큼 선형으로 증가하게 된다.

그러다 네트워크에 문제가 생기는 순간에는 cwnd의 크기를 절반으로 줄인다.

Slow Start

처음에는 네트워크 상황을 잘 모르기 때문에 무작정 큰 사이즈를 보내면 막힐 수 있으므로 조심스럽게 접근해야 한다. 따라서 제일 처음에 시작할 때는 세그먼트 하나를 보낸다. 즉 cwnd의 처음 시작 값은 1MSS가 된다. 이후에는 세그먼트를 지수적으로 늘려가면서 보낸다. exponential increase로 진행하다가 ssthresh를 정해놓고 이후에는 additive increases로 스위칭하는데 그 이유는 경험적으로 congestion이 발생할 가능성이 있기 때문이다. 이 단계를 congestion avoidance라고 한다.

Multiplicative decrease

loss가 발생했다고 판단할 수 있는 근거는 두 가지 이다.

  • timer expired
  • 3 dup Acks

이 중에 timer expired가 네트워크가 더 혼잡하다. 그 이유는 뒤에 있는 세그먼트 들이 다 날아간 상황이기 때문이다. TCP series 2 Reno는 이 둘의 대처 방식에 차이를 뒀다. 3 dup Acks의 경우는 현재 cwnd 크기를 1/2로 줄인다. 타이머의 경우에는 slow start으로 돌아가서 처음부터 시작한다.

TCP throughput

TCP의 보내는 속도는 네트워크가 결정하기 때문에 고정된 값이 아니다.

굳이 구하자면

avg TCP throughput = 3/4 W/RTT임

TCP Fairness

같은 라우터에 연결된 독립적인 TCP에서 결과적으로 모두 같은 1/n의 전송 속도를 가질 수 있을까? ㅇㅇ 가질 수 있음

네트워크를 혼잡하게 만들지 않는 범위 내에서 최대치의 전송 속도를 찾아가면서 동시에 모든 TCP connection들이 각각 1/n씩 공평하게 자원을 사용한다. (connection 관점에서 봤을 경우. 만약 한 호스트가 TCP connection 10개 가지고 다른 호스트는 TCP connection이 1개라면 전자가 10배 더 사용하는 것임)

참고
http://www.kocw.net/home/search/kemView.do?kemId=1312397
http://www.kocw.net/home/cview.do?mty=p&kemId=1169634

0개의 댓글