[Network] 전송계층 3
💻CS/Network

[Network] 전송계층 3

728x90
반응형

http://www.kocw.net/home/cview.do?mty=p&kemId=1169634 

 

 

Flow Control

  • TCP에서 가장 중요함!
  • 하지만 동작은 너무나 직관적이고 단순함! 

 

플로우 컨트롤의 사전적 의미는 아래와 같다. (from wiki)

데이터 통신에서 흐름 제어는 더 빠른 송신자가 느린 수신자를 제압하지 못하도록 두 노드 간 데이터 전송 속도를 관리하는 과정이다

간단하게 보자면 sender가 전송하는 데이터의 속도(양)을 조절하는 일련의 과정을 말하는 것이다! 

 

앞서 봤던 것 처럼 A,B로 클라이언트와 서버가 있다고 가정해보자. 

 

A (Client) B (Server)
Send Buffer Send Buffer
Receiver Buffeer Receiver Buffeer

 

여기서 A가 B에게 데이터를 보낼 때 자기 맘대로 보내고 싶은대로 보내면 안된다. 중요한 건 받는 사람(B의 receive buffer)의 능력에 맞춰서 보내줘야한다. 실제로 receiver가 받을 수 있는 만큼 보내줘야 의미가 있는것 이고, 이러한 과정을 flow control 이라고 한다. 흐르는 물의 양을 조절하는 것과 같이 보내는 데이터에 대해서도 관리가 필요하다는 것이다!

 

Receiver의 크기가 좌우하기 때문에 Receiver-Drive라고도 한다. 

 

과연 그렇다면 A의 Sender는 B의 Receiver의 현재 상황을 어떻게 알 수 있을까??

계속적으로 B의 Receiver가 A의 Sender에게 space에 대한 정보를 보내줘야 한다. 이 때 해당 정보는 TCP Segment Header부분의 Receiver Buffer Size라는 필드에 저장되어 전송된다. Sender는 이 정보를 기반으로 보내야 할 데이터의 양(속도)를 조절하게 되는 것이다. 

 

맨 처음 말했던 것 처럼 중요한 기능이긴한데 너무나 단순한 구조로 구성되어있고 수행되고 있다. 

 

이런 경우도 생각해 볼 수 있을 것 이다. 만약 Receiver가 현재 가용 가능한 space가 0이다 라고 A의 sender에게 리포트하게 되면 A는 어떤 액션을 취해야 할까? 0을 리포트 받았다고 해서 무작정 기다려야 할까?? 

 

그건 아니다!

 

A의 Sender는 마냥 기다리는게 아니라 주기적으로 Segment를 보내게 되는데 이때 데이터 부분은 포함하지 않고 보내거나 작은 용량(1바이트) 수준 정도만 담아서 Receiver에게 보내게 된다. 이렇게 아무 의미없는 Segment를 보내는 것은 계속적으로 receiver의 buffer size를 얻기 위해서이다. receiver가 보내주는 ACK에 현재 상황이 담겨 있기에, 계속 쿡쿡 찌르면서 상황을 체크하는 것이다. 

체크하다가 빈 공간이 있다는 정보를 받게 되면 그 때는 데이터를 담아서 전송하게 되는 것이다. 

 

 

connection management 

데이터를 교환하기 전에 반드시 해야할 단계이다. 이름도 그 유명한 TCP 3-way Handshake !

왜 이름이 그런가 하면 말 그대로 3번 왔다갔다해서 그런 것이다...

 

TCP 3-way Handshake

 

수행 순서는 다음과 같다. 

 

1. 클라이언트 > 서버 

 : 나 너랑 TCP 열고 싶어!

클라이언트는 서버에게 TCP SYN segment를 전송한다. 이 때 Seq #도 같이 알려줘야 한다.

(SYN segment : 연결 요청때에만 segement의 헤더 flag에 담기는 값(1비트)으로 데이터는 없다!)

 

2. 서버 > 클라이언트

 :  그래 열자!

서버는 SYN segment를 받고 클라이언트에게 SYNACK를 전송한다. 이에 서버는 버퍼를 할당하고, seq #를 정한다. 

그리고 ACKBIT도 보내고 기존 클라이언트 seq #에 +1하여 전송한다. 

 

3. 클라이언트 > 서버 

 : ㅇㅋㅇㅋ (데이터는 옵션)

클라이언트는 SYNACK를 받고 ACK응답을 다시 서버에게 보내준다. 이 때 클라이언트는 TCP 버퍼와 변수를 할당한다. 

앞선 통신에는 데이터가 포함되지 않았으나 이 때 ACK에는 데이터가 포함될 수 있다(ex. HTTP Request)

 

이 일련의 과정이 이루어진 이후에 sender/receiver 버퍼가 생기는 것이다.

(3번째 반응을 받기 전까지 버퍼가 만들어지지 않는다고 한다. ) 

(3-way가 아니라 2-way면 서버측에서 확답을 받지 못하게 된다. )

 

TCP 연결 해제

TCP 연결을 해제하려면 아래와 같은 단계를 거쳐야 한다. 

 

1. 클라이언트 > 서버 : FIN 

 클라이언트는 서버에게 FIN 세그먼트를 전송한다. 

 

2. 서버 > 클라이언트 : FIN + ACK

 서버는 전송된 FIN을 받고 그대로 다시 보내고 ACK 또한 전송해준다. 

 

3. 클라이언트 > 서버 : ACK

 클라이언트는 서버에서 ACK를 전송하게 되는데 이 때 Sender/Receiver buffer의 메모리를 해제하지는 않는다. 

왜냐하면 클라이언트가 서버에게 보낸 ACK가 혹여나 유실될 경우 서버가 다시 요청해올 텐데, 이를 대비하기 위함이다. 

그래서 timed wait이라는 텀을 두고 천천히 메모리를 해제하게 된다. 즉 서버가 다시 보내올 FIN에 다시 ACK을 전송해주기 위한 메모리 정보가 필요하기에 시간을 두고 보유하고 있는 것이다. 

 

4. 서버가 ACK를 받고 연결 종료

 

 

아래는 TCP 클라이언트/서버의 라이프사이클이다. 위 SYN > SYNACK > ACK 과정과 종료까지의 일생을 나타낸 것이다. 

 

congestion control

앞서 봤던 TCP의 중요한 특징에는 Reliable Data Transfer, Flow Control 그리고 Congestion control이 있었다. 

요놈은 무슨 제어를 해주는걸까?

 

앞서 봤던 A와 B 사이에는 무형의 네트워크가 존재하는데, 사실 receiver의 현상황 뿐만 아니라 중간 전달자의 역할을 하는 네트워크의 능력을 함께 고려해줄 필요가 있다. 

 

예를 들어 네트워크는 5개, 리시버는 10개 처리가 가능하다고 하면 sender는 몇 개나 보내야 할까? 

반대로 네트워크는 10개, 리시버는 5개 처리가 가능하다면 몇 개나 보내야 할까? 

 

예상이 되었겠지만, receiver의 한계와 network의 한계를 함께 고려한 의사결정을 해줘야 한다. 항상 sender가 보내는 데이터의 양은 네트워크과 리시버 중 상태가 젤 안좋은 것을 기준으로 조절해줘야 한다. (작은 쪽에 맞춰야 원활해짐)

 

앞서는 receiver의 상태는 flow control을 통해 receiver가 보내주는 정보를 통해 알 수 있었지만, network의 상태는 어떻게 알 수가 있을까?

 

바로 Congestion Control을 통해 네트워크 상황을 얻어낼 수 있다. 

 

그 전에 생각해보면 네트워크는 대부분이 공용이다. 이에 수 많은 사용자들이 본인의 네트워크가 아니기 때문에 네트워크 상황을 고려하지 않고 데이터를 많이 보내게 된다. 이에 당연히 과부하가 오고 막히게 되는 건 당연하다. 여기서 막힌다는 것은 고속도로에 차가 막히는 것과 똑같다. 

 

당연히 TCP한테는 안좋은 상황이다. 왜냐하면 막히게 되면 내가 전송하고자 하는 패킷이 제대로 전송이 되지 않는다는 것이고, 이에 TCP는 계속 재전송하게 될 것이다. 이 상황이 계속 반복되면서 상태가 계속 악화되는 것이다.

(즉 네트워크가 막히면 TCP는 죽는다.😇 )

 

그러니 네트워크가 막히면 안되니, TCP는 네트워크가 막히지 않도록 해줘야 한다. (나름 주 업무) 

이에 데이터를 보내는 속도/양을 줄이게 되고, 각자 자신을 위해 줄이다 보면 결국 서로를 위해 줄이게 되는 모습을 볼 수 있다. 

 

자 이제 다시 돌아와서 네트워크의 현재 상황을 어떻게 알 수 있을까?

아까는 Receiver가 직접적으로 알려줬지만, 네트워크의 경우 2가지 접근 방식을 고려해볼 수 있다.

 

  • Network-Assisted Congestion Control
    • Router가 시스템에게 피드백을 준다. 
      • 현재 자신의 queue 상황 등 정보를 전달하여 체크할 수 있도록 해준다.

하지만 라우터는 그럴 시간이 없이 바쁘고, 실제로 구현되어 있지 않은 방식이라고 한다. 

 

이에 실제로 구현된 방식은 다음과 같다.

 

  • End-End Congestion Control
    • 네트워크에서 정보를 주진 않는다. 
    • 내부 상황을 유추하여 체크하고 진행한다. 
    • TCP에 ACK가 어떻게 동작하는지를 갖고 네트워크 상황을 유추하는 것이다. 
    • 유추이기에 아주 정확하진 않다. 

이 방식을 통해 피드백을 받으면서 sender가 보낼 양을 늘이거나 줄이거나 선택하게 된다. 

실제로 어떤 파일을 다운받을 때 다운로드 속도가 일정하지 않고 계속 변화하는 것은 네트워크의 상태를 유추하여 sender buffer size를 조정하기 때문이라고 봐도 될 것 같다.

 

끄읕

728x90
반응형