Skip to content

Latest commit

 

History

History
247 lines (132 loc) · 14.9 KB

TCP.md

File metadata and controls

247 lines (132 loc) · 14.9 KB

1회차

TCP 3-way handshake와 4-way handshake : 연결 설정과 해제 과정

TCP segment

TCP segment는 데이터 통신 시 TCP에 해당하는 4계층에서 만들어지는 데이터 단위블록이다.

하나의 TCP segment = TCP 헤더 + 데이터 로 이루어져있는데,

헤더에는 전송과 관련된 정보들이 담기고,

데이터에는 윗 계층에서 전달받은 데이터 블록 전체가 들어간다.

즉, 3계층 IP 단위블록을 4계층에서 전달받으면 그 앞에 4계층 통신과 관련된 옵션 사항들을 담은 헤더를 앞에 추가하고 다음 계층으로 보내주는 방식이다. 3강-25

TCP의 헤더는 위와 같이 구성되어있는데, 이중에서 우리가 주목해야 하는 부분은

  • sequence number
  • acknowledgement number
  • not used와 receive window 사이에 여러 알파벳이 쌓여있는 TCP플래그 (코드비트) 부분

이렇게 세가지이다.

각 코드비트는 1bit씩 차지하며 0과 1로 다음을 의미한다

  • U = URG = urgent data
  • A = ACK = Acknowledgement
  • P = PSH = Push data now
  • R = RST = Reset
  • S = SYN = Synchronize
  • F = FIN = Finish

우리는 이중 볼드처리한 세가지 코드비트만 확실히 알아가자 !

  • sequence number
    • 현재 전송하는 segment 블록 주소의 첫번째 바이트 숫자를 전달하는 곳이다
    • 즉, sequence number= 15 → A : “나 이번 segment에서 15번 데이터부터 보낸다”
  • acknowledgement number
    • 상대에게 받아야 하는 다음 블록 주소의 첫번쨰 바이트 숫자를 알려주는 곳이다.
    • 즉, acknowledgment number= 30 → A: “B야, 지난번에 너 데이터의 29번까지 받았으니까, 이 다음 답장 때는 30번 데이터부터 보내주면돼.”

여기서 코드비트의 역할은 sequence number와 함께 어떠한 데이터를 전달할 때는 SYN = 1

데이터를 잘 받았다는 메시지를 전달할 때엔 acknowledgement number와 함께 ACK = 1

를 사용해주면 된다.

본격적으로 handshake 통신에 대해서 알아보자.

handshake?

A와 B가 본격적인 데이터 통신을 하기 전과 후, 말그대로 ‘손을 흔들며 인사’를 나누는 과정이다.

  • 3-way handshake : 통신을 시작하기 위한 과정
  • 4-way handshake : 통신을 종료하기 위한 과정

그렇다면 왜 2-way handshake는 없을까?

2-way handshake로 통신을 할 경우,

  • 클라 : 서버야, 너 이제부터 나랑 통신 하자 ! (SYN)
  • 서버 : 응 알겠어, 나 연결한다! (ACK)

이렇게 대화가 끝나게 되는데, 이럴 경우 문제점은 서버측에서 답변한 내용이 클라에게 전달이 되지 않는 경우에 발생한다.

저대로 통신이 끝나버리면, 서버는 자신이 클라의 요청을 잘 받았다는 사실을 클라도 알고 있는지 알 방법이 없다.

따라서, 마지막에 클라 또한 서버의 답변을 잘 받았다는 재답변을 한번 더 보내주어 통신연결을 확실히 하기 위해 3-way handshake가 필요한 것이다.

3-way handshake

3강-48

통신을 시작하는 시나리오는 다음과 같다

클라 : SYN = 1, sequence number = x

나 x바이트부터 데이터 보내기 시작하고 싶어. 통신을 요청해!

서버 : ACK = 1, acknowledgement number = x+1, SYN = 1, SYN = y

너의 데이터 요청 잘 받았어! x바이트 잘 받았고 그 다음인 x+1부터 보내면 돼! 그리고 나도 데이터를 보낼게. 내 데이터는 y바이트부터 보내기 시작할게.

클라 : ACK = 1, acknowledgement number = y+1

너의 데이터 요청 잘 받았다는 응답과 추가로 보낸 데이터도 잘 받았어! 그 다음인 y+1부터 보내면 돼.

이렇게 일정 시간 내에 서로가 통신을 시작할 준비가 되었다는 것을 확인한 후에 통신을 시작하기 때문에 안전하게 데이터를 주고받을 수 있다!

4-way handshake

3강-51

필요한 데이터를 모두 주고 받고 통신을 종료하는 시나리오는 다음과 같다.

클라 : FIN = 1, sequence number = x

x바이트 데이터를 보내면서 이번 통신을 종료할게. (FIN 코드를 보낸 이후로 클라는 더이상 데이터를 보낼 수 없음)

서버 : ACK = 1, acknowledgement number = x+1

x바이트까지 데이터 받았고, 너의 통신 종료 요청 잘 알겠어!

서버 : FIN = 1, sequence number= y

y바이트 데이터를 보내면서, 나도 통신 완전히 종료할게. (서버도 더이상 데이터를 보낼 수 없음)

클라 : ACK = 1, acknowledgement number = y+1 (이제 데이터를 보내지도, 받지도 못함)

y바이트까지 데이터 받았고, 너의 통신 종료 요청 잘 알겠어.

마지막으로 서버가 클라가 보낸 ACK 메시지를 확인한 후에 통신이 완전히 종료된다.

여기서 알아두면 좋은 포인트는

  • 2-way handshake가 안전하지 못한 것과 동일한 이유로, 4-way handshake 시나리오에서 가장 마지막에 클라가 서버에게 보낸 ACK 메시지가 중간에 유실될 수 있기 때문에, 서버가 만약 이 ACK을 못받고 다시한번 이전의 메시지를 전송하는지를 일정 시간 기다려본 후에, 답이 오지 않으면 답변을 잘 받은 것으로 알고 완전히 통신을 종료한다.
  • 4-way 중 2,3 단계에서 서버가 연속적으로 메시지를 보내는데, 1) 클라의 통신 종료 요청을 잘 받았다는 답변과, 2) 서버도 이제 통신을 종료할 준비가 되었다. 통신을 종료하자. 라고 말하는 메시지로 이루어진다. 두 메시지 단계가 분리된 이유는, FIN을 보내면서 클라는 더이상 데이터를 보낼 수 없게 되었지만, 서버는 아직 데이터를 보낼 수 있는 상태이기 때문에 서버도 통신을 종료하겠다고 선언하기 전에 추가로 더 보내야할 데이터가 있으면 보낼 수 있는 시간이 사이에 주어진다. 그러나 대부분의 경우, 그사이에 추가적으로 보낼 데이터가 없기 떄문에 2번 메시지와 3번메시지를 동시에 전송할 때도 많다고 한다. 즉, ACK = 1, acknowledgement number = x+1 , FIN = 1, sequence number = y 을 하나의 메시지를 통해 전달하는 것이다.

TCP/IP 흐름제어와 혼잡제어

흐름 제어

  • 송신(호스트) <> 수신(호스트)

흐름 제어는 수신측과 송신측의 데이터 처리 속도 차이를 해결하기 위한 기법이다.

만약 송신측의 전송량이 수신측의 처리량보다 많은 경우, 전송된 패킷은 수신측의 큐를 넘어서 손실될 문제가 발생할 수 있기 때문에 송신측의 패킷 전송량을 제어하게 된다.

1. Stop and Wait 방식

stop_and_wait png

  • 매번 전송한 패킷에 대해 응답을 받아야만 그 다음 패킷을 전송할 수 있다.
  • 구조가 간단한 대신, 하나를 주고 하나를 받기 때문에 비효율적이다.

2. 슬라이딩 윈도우(Sliding Window)

수신측에서 설정한 윈도우 크기만큼 송신측에서 확인 응답 없이 세그먼트를 전송할 수 있게 하여 데이터 흐름을 동적으로 조절하는 기법이다.

이처럼 슬라이딩 윈도우 기법을 통하여 송신 버퍼의 범위는 수신 측의 여유 버퍼 공간을 반영하여 동적으로 바뀜으로써 흐름제어를 수행한다.

  • 윈도우는 전송, 수신 스테이션 양쪽에서 만들어진 버퍼(Buffer)의 크기이다.
  • 윈도우의 크기 = (가장 최근 ACK로 응답한 프레임의 수) - (이전에 ACK 프레임을 보낸 프레임의 수)
  • 슬라이딩 윈도우 기법은 Stop and Wait 기법의 비효율성을 개선한 기법이다.
  • ACK 프레임을 수신하지 않더라도 여러 개의 프레임을 연속적으로 전송할 수 있다

error_flow_control_2 png

위와 같은 구조에서 데이터 0과 1을 전송했다고 가정하면 슬라이딩 윈도우의 구조는 아래와 같이 변한다. 윈도우의 크기는 전송한 데이터 프레임만큼 왼쪽 경계가 줄어들게 된다.

error_flow_control_3 png

이때 수신측에서 ACK라는 프레임을 받게 된다면 전송측은 0과 1 데이터를 정상적으로 받았음을 알게 되고, 전송측은 ACK 프레임에 따른 프레임의 수만큼 오른쪽으로 경계가 확장된다.

error_flow_control_4 png

혼잡 제어

  • 송신측의 데이터 전달과 네트워크의 데이터처리 속도 차이를 해결하기 위한 기법

송신측의 데이터는 지역망이나 인터넷으로 연결된 대형 네트워크를 통해 전달된다. 하지만 이러한 네트워크 상의 라우터가 항상 한가로운 상황은 아니다. 만약, 한 라우터에게 데이터가 몰릴 경우 다시 말해 혼잡할 경우, 라우터는 자신에게 온 데이터를 모두 처리할 수 없다.

그렇게 되면 호스트들은 또 다시 재전송을 하게 되고 결국 혼잡을 가중시켜 오버플로우나 데이터 손실을 발생시킨다. 따라서, 이러한 네트워크의 혼잡을 피하기 위해 송신측에서는 보내는 데이터의 전송 속도를 강제로 줄이게 된다.

1. AIMD

AIMD(Additive Increase / Multiplicative Decrease)라고 불리며, 합 증가 / 곱 감소라고 부른다.

처음에 패킷을 하나씩 보내고 이것이 문제없이 도착하면 window 크기(단위 시간내에 보내는 패킷의 수)를 1씩 증가시켜 가면서 전송하는 방법이다. 만일 패킷 전송을 실패하거나 일정한 시간을 넘으면 패킷 전송 속도를 절반으로 줄이게 된다.

이 방식은 공평한 방식이다. 이 방식을 사용하는 여러 호스트가 한 네트워크를 공유하고 있으면 나중에 진입하는 쪽이 처음에는 불리하지만 시간이 흐르면 평형 상태로 수렴하게 되는 특징이 있다.

문제점은 초기에 네트워크의 높은 대역폭을 사용하지 못하며 오랜 시간이 걸리게 되고 네트워크가 혼잡해지는 상황을 미리 감지하지는 못한다.

즉, 네트워크가 혼잡해지고 나서야 대역폭을 줄이는 방식이다.

2. Slow Start

AIMD 방식은 네트워크의 수용량 주변에서는 효율적으로 작동하지만 처음에 전송 속도를 올리는 데 걸리는 시간이 너무 길다는 단점이 있다.

Slow Start 방식은 AIMD 방식과 마찬가지로 패킷을 하나씩 보내는 것부터 시작하고 이 방식은 패킷이 문제없이 도착하면 각각의 ACK 패킷마다 Window Size를 1씩 늘린다. 즉, 한 주기가 지나면 Window size가 2배가 된다.

따라서 전송 속도는 AIMD와는 다르게 지수 함수꼴로 증가하게 된다. 대신 혼잡 현상이 발생하면 Window Size를 1로 떨어뜨리게 된다.

처음에는 네트워크의 수용량을 예상할 수 있는 정보가 없지만 한번 혼잡 현상이 발생하고 나면 네트워크의 수용량을 어느 정도 예상할 수 있으므로 혼잡 현상이 발생하였던 Window Size의 절반까지는 이전처럼 지수 함수 꼴로 Window Size를 증가시키고 그 이후부터는 완만하게 1씩 증가시키는 방식이다.

  1. 초기 혼잡 Window Size 1로 전송 = 전송 호스트는 하나의 패킷만 전송
  2. 수신 호스트로부터 수신응답을 수신하면 윈도우의 크기를 2로 하여 전송
  3. 수신 호스트로부터 수신응답을 수신하면 윈도우의 크기를 4로 하여 전송
  4. 수신 호스트로부터 수신응답을 수신하면 윈도위의 크기를 8로 하여 전송

error_flow_control_10 png

  • 미리 정해진 임계 값(threshold)에 도달할 때까지 윈도우의 크기를 2배씩 증가시킨다.
  • Slow Start란 이름을 사용하지만, 매 전송마다 두 배씩 증가하기 때문에 전송되어지는 데이터의 크기는 지수 함수적으로 증가한다.
  • 전송되어지는 데이터의 크기가 임계 값에 도달하면 혼잡 회피 단계로 넘어간다.

3. 혼잡 회피(Congestion Avoidance)

3강-65

윈도우의 크기가 임계 값에 도달한 이후에 데이터의 손실이 발생할 확률이 높아지게 된다. 이는 데이터를 전송함에 있어서 조심하는 단계이다.

전송한 데이터에 대한 ACK를 받으면 윈도우의 크기를 1씩 증가시킨다.

전송하는 데이터의 증가를 왕복시간 동안에 하나씩만 증가시킨다.

  • 수신 호스트로부터 일정 시간 동안까지 ACK를 수신하지 못하는 경우
  1. 타임아웃의 발생

    네트워크에 혼잡이 발생했다고 인식> 윈도우의 크기를 즉, 세그먼트의 수를 1로 줄임> 동시에 임계 값을 패킷 손실이 발생하였을 때의 윈도우 크기의 반으로 줄임

  2. 빠른 회복(Fast Recovery)

    빠른 회복은 Congestion이 발생했을 때 Window size를 1로 줄이지 않고 반으로 줄이고 선형 증가시키는 방법이다. 이는 AIMD의 AI 즉, Additive Increase 하는 방법이다.

    Fast Recovery를 적용하면 혼잡 상황을 한 번 겪고 나서부터는 순수한 AIMD 방식으로 동작하게 된다.

  3. 빠른 재전송(Fast Retransmission)

    3개의 연속된 중복 ACK를 수신하는 경우에 패킷의 손실로 간주하여 타임아웃이 발생하기 전에 해당 패킷을 재전송한다. 그리고 이러한 현상이 일어난 것은 약간의 혼잡이 발생한 것으로 간주하여 Window Size를 반으로 줄인다.

  4. TCP Reno

    N개의 중복 ACK 발생 시 ssthresh(slow start threshold)값을 Congestion Window(cwnd) 사이즈의 반으로 줄여 빠른 복구(Fast Recovery)를 수행하여 선형적 증가를 하게 되며, TCP Time Out에 이르면 Slow Start를 시작한다.

  5. TCP Tahoe

    N개의 중복 ACK 발생 시 바로 Slow Start를 시작한다.

TCP Tahoe와 TCP Reno는 ssthresh(slow start threshold) 값까지 지수적 증가(Slow-Start)를 하게 되고 ssthresh를 넘어서면 선형적 증가(Additive Increase)를 하는 것까지는 동일하다. 차이가 생기는 기준은 N개의 중복 ACK가 발생할 경우이다.