IT 그리고 정보보안/Knowledge base

TCP (Transmission Control Protocol)

plummmm 2021. 4. 11. 12:32
반응형

소켓 프로그래밍을 하기 위해 전송 계층 프로토콜 (TCP, UDP)에 대해 먼저 알아보자.

먼저 TCP의 구조를 한번 봅시다.

 

송,수신지 포트, Seq. num, flag 등등 복잡한 구조를 갖고 있다.

각각의 내용들은 뒤에 하고 먼저 TCP의 특징 몇가지를 간단하게 정리하겠다.

 

1. Point-to-Point 즉, 송신자와 수신자 1:1 통신이다.

3-ways-handshaking(3HSK) 을 통해 세션을 맺은 상태에서 통신하므로 1:1 통신이다.

이렇게 세션이 맺힌 상태에서는 언제든지 데이터를 주고받을 수 있는 상태이므로

TCP는 연결 지향형(Connection-oriented), 양방향형(Full Duplex) 이라고 말할 수 있다.

 

2. 신뢰할 수 있는 통신이다. 

데이터를 보내고 잘 갔는지 확인하고 제대로 전송되지 않으면 다시 재전송하는 특징이 있다.

그리고 보내는 모든 바이트에 번호를 메김으로써 올바르게 전송됐는지 확인이 가능하다.

 

3. 송신, 수신 버퍼가 있다.

송신 버퍼, 수신 버퍼를 가짐으로써 좀더 유연한 통신이 가능하게 한다.

 

 

4. 흐름제어 기능이 있다.

windows 라는 개념이 있다. 수신 버퍼의 크기를 말하는데, 이 버퍼가 넘치지 않도록

제어가 가능하다.

 

그리고 TCP는 신뢰성이 있다고 했다.

그래서 ACK를 받을 때 까지 전송한 패킷의 복사본을 저장한다.

 

 

TCP Sequence Number,  ACK Flag

TCP의 Sequence Number 와 ACK에 대해 알아보자.

 

 

TCP 헤더에서 분홍색 표시된 부분이다.

TCP는 모든 바이트들의 첫부분을 Seq.# 로 표시한다.

그리고 다음번에 받을 패킷의 Seq# 을 가르키는 것이 ACKs 이다.

 

 

위 그림을 보면 먼저 seq#42인 패킷을 전송하고 응답을 요청하는 seq#은 79이라고 

패킷에 ACK=79 포함시켜 전송을 하고 있다.

 

수신한 쪽은 79번을 전송하고 43번을 요청하고 있다.

그러고 나니 다시 최초 송신 측에서 43번과 ACK=80으로 80번을 요청하고있다.

 

설명을 더이상 상세하게 할 자신이 없다. 이 내용에 대한 다른 상황을 한번 알아보겠다.

 

먼저 ACK 패킷을 손실하였을 때 이다.

seq#92인 데이터를 8바이트 보내게 되면 99까지 받게 되고

다음 번 seq#100 을 요청하게 될 것이다. 근데 ACK=100으로 요청하는 패킷이

손실이 되었다. 응답을 못받은 송신측은 다시 재전송하게 된다.

 

다음은 ACK가 오기전에 다음 전송을 하여 ACK가 중첩되는 상황이다. 

송신자가 데이터 전송을 ACK가 오기전에 한번 더 해버렸고,  수신측에서 ACK를 둘다 보냈는데, 알 수 없는 이유로 지연이 되어 Timeout 되고 난 후에 도착하여 송신측은 seq#92를 다시 한번 보낸다.

근데 수신측은 이미 119번 까지 다 받았기 때문에 ACK 120만 요청한다. 

 

TCP 흐름제어

TCP의 흐름제어에 대한 내용을 알아보자.

 

흐름제어에 필요한 recv windows size 필드를 나타낸 그림이다.

 

흐름제어란 말 그대로 전송하는 패킷의 흐름을 제어하는 것이다.

너무 빠르지 않게, 넘치지도 않게 적당하게 흐름을 조절하는 것.

 

흐름제어에는 RcvBuffer(수신 버퍼)와 RcvWindow 개념에 대한 이해가 선행되어야 한다.

위 그림을 보면 rcvBuffer 안에 rcvWindow 가 있다. 윈도우는 버퍼에서 남은 공간을 나타낸다.

 

수신측에서 버퍼에 있는 데이터를 읽으면 윈도우는 늘어날 것이며 버퍼에 데이터가 쌓일 수록 윈도우 크기는 줄어들 것이다. 이 두가지로 버퍼의 오버플로우를 방지할 수 있다.

 

 

RTT(Round Trip Time), Timeout

RTT와 Timeout 값에 대해서 알아봅시다.

RTT는 서버와 클라이언트 간에 통신 왕복 시간을 말한다.

Timeout value는 타임 아웃값, 이 값이 지나도록 응답이 없으면 재전송하는 것이다.

 

RTT와 Timeout 값은 서로 연관성이 많다. 왜냐?

RTT값을 미리 예상하여 Timeout value를 설정해야 하기 때문이다.

 

Timeout 값이 RTT보다 커야한다.

너무 짧으면 타임아웃이 너무 많이 일어나 쓸데없는 재전송(retransmission)이 많이 생길 것이다.

반면에 너무 길면 세그먼트 손실에 대한 응답이 너무 느릴 것이다.

 

 

TCP 연결 관리

TCP연결에 대해 알아보자. TCP 연결이 되기 전에 먼저 클라이언트와 서버는 세션을 맺는다.

이 과정을 3 ways Hand-shaking(3HSK라고 하겠음) 이라고 하는데, 뭐 말그대로 3번 악수하는 것이다.

 

위 그림에 U,A,P,R,S,F 보임? 저게 이제 TCP 플래그인데, 데이터는 아니고

세그먼트 메세지의 용도?목적? 등을 표시하는 비트라고 생각하면 된다.

3HSK를 하기 위해 위 플래그들을 설정한 데이터 세그먼트들이 송수신 되면서 세션이 맺어진다.

 

 

솔직히 난 처음 배울때 SYN, SYN ACK, ACK 이렇게 외웠는데,

외울 것도 없다. 그냥 저렇게 알고 있음 된다.

클라이언트 측은 능동적인 개방이다.connect 함수로 SYN을 날리고 이 때 클라이언트 측 ISN을 정한다.

(ISN이란 Initial Sequence Number의 약자로 말그대로 초기화된 seq# 값은 랜덤하고 sender가 정한다.)

 

그리고 SYN 을 날릴 때 옵션을 설정한다.

MSS : 한번의 받을 수 있는 데이터 최대 사이즈 (자세한 설명 뒤에)

Wndow size : 수신 가능한 버퍼의 사이즈를 알려주는 윈도우 크기

time-stamp : 패킷이 사라졌다가 다시 나타나는 경우에 발생하는 손실에 대한 옵션(코딩 시 신경안써도 되는거)

SYN,ACK를 받으면 connect가 리턴된다.

 

서버 측은 SYN을 받고 서버 측 ISN을 설정하고, 버퍼 공간을 할당한다. 그리고 SYN, ACK를 보낸다.

세션이 맺어지고 나면 accept 리턴값을 받는다.

 

이렇게 세션이 맺은 상태에서 서로 데이터를 교환하고 이제 연결을 닫을 시간이다.

 

 

아까 말한 4HSK 이다.

 

세션을 끊을 때도 마찬가지다. 끊을 땐 4HSK 이다.

클라이언트 측에서 FIN을 먼저 보낸다. 이걸 또 능동적인 폐쇄라고 한다.(HTTP에서는 서버가 폐쇄함)

받으면 서버가 ACK와 FIN을 날리고 클라이언트 측으로 부터 ACK를 받으면 종료된다.

여기에 부가 내용이 더 있는데, 따로 설명하겠다.

 

클라이언트와 서버의 생명 주기(Life cycle) 을 보자.

먼저 클라이언트의 생명 주기이다.

 

 

다음은 서버의 생명 주기이다.

 

 

TCP 혼잡제어

TCP 혼잡 제어 (Congestion Control)에 대해서 알아보자. 이건 flow control 과는 다른 개념이다.

많은 클라이언트 들이 많은 데이터를 전송하면 네트워크는 그것을 처리하는데 힘이 든다. 그래서 나온것이 혼잡 제어.

이 혼잡제어를 하기 위해 Congestion Windwos 라는 값에 대해 알아야 한다.

 

 

congwin는 송신측에 두는 값으로 congwin 값 만큼만의 세그먼트만 전송하도록 하는 것이다.

쉽게 말해 송신 측에서 ACK를 받지 않고 전송할 수 있는 세그먼트 수 라고 보면된다.

위 그림을 보면 이해할 수 있다.

 

자 그럼 혼잡제어를 하기 위해서 TCP는 어떤 방법들을 쓸까.

몇가지 있는데 알아보겠음.

 

1. Slowstart algorithm

슬로우 스타트, 느리게 시작한다는 말이다.

먼저 전송할 때 Congwin을 1로 초기화 시킨다.

그럼 1 세그먼트만 전송이 되겠지?

그렇게 보낸 것이 ACK가 오면 Congwin++ 한다.

 

 

 

위 그림을 보면 ack 하나 받으면 congwin가 1증가하고, 2개 받으면 2증가한다.

이게 보통은 지수적으로 증가한다. 제곱으로 증가한다는 말임.

어느 정도 한계에 다다르면 (라우터가 패킷을 폐기할 때 혹은 정해둔 한계점(threshold)보다 congwin이 클때)

더 이상 congwin이 증가하지 않는다. 

 

2. Congestion Avoidance

손실되는 패킷을 다루는 방법이다. AIMD (Additive Increase, Multiplicative Decrease) 라는게 있는데,

합 증가/ 곱 감소 라는 아주 직관적인 뜻을 가진 방식이다.

처음에 패킷을 하나씩 보내고 문제 없이 도착하면 창 크기를 1씩 증가시키면서 전송하는 방법이다.

만약 실패하거나 timeout이 되면 속도를 절반으로 줄인다.

 

이 방법은 여러 호스트가 하나의 네트워크에 있을 때 처음 진입하는 쪽이 불리하지만

시간이 지날수록 평형하게 수렴하는 특징이 있다. 그래서 TCP is fair 라고들 한다..

반응형