현실 TCP 통신은 패킷 하나하나만 주고받는게 아닌 우르르 패킷을 보내고 또 우르르 패킷을 받는 파이프라인 프로토콜 방식을 사용한다. 파이프라인 프로토콜의 대표적인 규칙은 ARQ (Automatic Repeat reQuest) 프로토콜이 있고 여기에는 go-back-N 과 selective repeat 두 가지 동작방식이 있다. (TCP는 ARQ보다 좀더 발전된 방식 사용)
Pipeline protocol을 준수하여 정보를 한 번에 여러개를 보내게 된다고 했을 때 보내지는 대량의 정보에 대해 무작정 보내는 것이 아닌 일종의 기준이 있다. 이때 Go-Back-N 방식은 sender에서 전송할 패킷의 개수를 정하는 방식이다.
이때 전송자가 보낼 수 있는 연속적인 패킷의 최대 개수 기준이 있는데 이를 window size라고 부른다. 다시말해 Go-Back-N 방식에서 윈도우 사이즈 N은 한 번에 N개의 패킷을 전송할 수 있는 능력을 말한다. window size는 아직 receiver가 받지 못한 패킷들을 sender가 저장할 수 있는 크기를 의미하기도 한다.
Go-Back-N 방식의 특징은 receiver가 약간 댕청하다는 것이다. 직접적인 패킷 교환전 receiver는 sequence number(예를들어 0)을 받고 하염없이 같은 넘버를 가진 패킷을 기다린다. 만약 시퀀스 넘버에 1이 담겨오면 ack만 보내고 또다시 시퀀스넘버 0이 담긴 패킷을 기다린다. 원하는 시퀀스넘버가 올 때까지 receiver는 계속해서 원하지 않는 시퀀스 넘버를 담은 Ack을 다시 sender에게 보낸다. 이렇게 되면 sender는 어떤 패킷부터 잘못보내졌는지 알 수 있기 때문에 잘못된 패킷의 시퀀스넘버부터 다시 차례차례 순서대로 재전송한다. 정리하자면 Go-Back-N 방식은 receiver 측에서 순서대로 받지 못한 패킷이 있다면 해당 패킷부터 다시 재전송 하는 방식이다.
GBN 방식이 버퍼에 있는 한 패킷이 유실되면 뒷패킷은 버퍼에 넣어두었다 다시 순서대로 모두 되돌려주는 방식이라면 selective repeat은 빠진 패킷만 개별적으로 receiver에게 돌려주는 방식이다. receiver 는 ACK이 순서대로 오든 말든, 그냥 받은 패킷에 대한 ACK을 보낸다. 그리고 버퍼공간에 받은 패킷을 쌓아둔다. 여기서 GBN과 차이가 드러나는데 Selective Repeat 방식에서는 수신자가 각 패킷을 개별적으로 처리하고 버퍼에 저장할 수 있어야한다는 것이다. 이는 패킷이 도착한 순서와 관계없이 각 패킷을 올바르게 저장하고 조립할 수 있도록 한다. Receiver가 좀더 똑똑한 덕분에 sender는 유실된 패킷만 보내주어도 Recevier가 알아서 순서까지 맞춰서 조합한다.
sender는 ACK을 받지 못한 모든 패킷에 대해 타이머를 계산한다. 여기서 타이머에 대해 설명하자면 sender는 각 패킷을 전송할 때 그 패킷에 대해 타이머를 시작한다. 이 타이머는 설정된 시간 동안 수신자로부터 해당 패킷의 ACK을 받지 못하면 만료된다. 타이머가 만료되면, 이는 해당 패킷이 수신자에게 제대로 도착하지 않았을 가능성이 있음을 나타내고. 이 경우 sender는 해당 패킷을 재전송하는 메커니즘이다.
시퀀스 번호(sequence number)는 각 패킷을 고유하게 식별하는 데 사용된다. 이 번호는 패킷의 순서를 유지하고, 동일한 패킷이 재전송되는 경우 중복을 구별하는 역할을 한다. 이때 (sender의 윈도우 크기 + receiver의 윈도우 크기)보다 시퀀스 번호의 최대 범위가 크거나 같아야 한다. 이유는 모든 가능한 패킷 상태를 고유하게 식별하기 위해서이다. 이를통해 재전송된 패킷이 원래의 패킷과 구별되며, 패킷의 순서를 정확히 추적할 수 있다.
지금까지만 보면 GBN보다 SR방식이 훨씬 좋아보일 수 있다. SR은 똑똑하게 유실된 패킷만 재전송하기 때문이다 하지만 문제는 SR은 Go-Back-N 과 다르게 각 패킷마다 타이머를 달아야해서 비용이 너무 커진다는 것이다.이렇게 모든 소켓마다 타이머를 다는 것은 현실적으로 힘들기 때문에 현실에서는 Go-Back-N 이나 cumulative ACK를 사용한다.
TCP의 가장 주요한 특징은 point-to-potint 라고 할 수 있다. (여기서 point to point 란 출발 소켓과 도착 소켓이 정해져있는 것으로 소켓 하나와 소켓 하나의 통신을 책임지는 것). 이는 다시말해 TCP통신은 클라쪽 프로세스와 서버쪽 프로세스 하나씩 쌍으로 관리한다는 것을 의미한다. 또한 full duplex data 특징을 가지고 있는데 이는 같은 커넥션에서 양방향으로 데이터가 흐른다는 것을 의미한다.
TCP 통신에서 receiver가 윈도우 사이즈에 해당하는 buffer 양이 초과할 만큼 반환하면 정보가 유실된 위험이 있는데 TCP는 Congestion Control 에 의해 데이터 유실 문제를 방지한다. (데이터 트래픽 양이 네트워크의 용량을 초과하지 않도록 조절)
각 레이어의 전송 단위(각 레이어 전송단위는 헤더 + 데이터로 구성)를 살펴보자. 먼저 애플리케이션 레이어의 전송단위는 메세지, 트랜스포트 레이어의 전송단위는 세그먼트(, 네트워크 레이어의 전송단위는 패킷, 링크레이어 (Wifi/LTE/3G) 의 전송단위는 Frame이다. (앞선 방식대로 Data에 패킷을 넣고 헤더에 메타데이터를 심는 방식). 이중 세그먼트를 자세히 살펴보자. 앞서 Congestion Control에 의해 데이터가 버퍼양을 초과하지 않도록 한다고 조절한다고 했다. 그렇다면 남은 버퍼 공간의 양을 알아야할텐데 이 정보가 바로 세그먼트 헤더의 receive window에 담겨있다. 받은 세그먼트에 대해 수신자 Buffer에 얼마만큼 빈공간이 있는지 피드백을 줄 때 피드백의 정보를 담는 공간이다. (TCP에서는 수신자가 곧 송신자임을 기억하자)
헤더에 보면 ACK도 확인할 수 있다. 여기서 TCP에서의 ACK는 GBN의 ACK와 약간의 차이가 있다. GBN에서는 손실된 패킷 이후의 모든 패킷을 재전송하는 반면, TCP는 보다 지능적인 방법(빠른 재전송, SACK)을 사용하여 필요한 패킷만을 재전송한다. 또한 Conetion control(혼잡 상황 관리) 덕분에 패킷 손실과 네트워크 혼잡 상황을 관리하는 데 더욱 효율적이다.
💡 흐름제어(Flow Control)
흐름 제어는 송신자와 수신자 사이의 데이터 전송 속도를 조절하여, 수신자가 처리할 수 있는 속도 이상으로 데이터가 전송되어 발생할 수 있는 버퍼 오버플로우를 방지합니다. 이는 주로 수신자의 버퍼 용량에 초점을 맞춘다.
만약 수신자의 애플리케이션이 데이터를 느리게 처리하면 Receive Window 크기가 줄어들고, 결과적으로 송신자는 데이터 전송 속도를 늦추게 된다.
💡 혼잡제어(Congestion Control)
혼잡 제어는 네트워크 내의 데이터 트래픽 혼잡을 감지하고 관리하여 네트워크 오버로드를 방지합니다. 이는 전체 네트워크의 트래픽 로드에 초점을 맞추고, 데이터 패킷의 손실이나 지연을 최소화하기 위해 설계되었다.
네트워크 경로상의 어떤 라우터가 과부하 상태가 되면 패킷 손실이 발생할 수 있다. 이를 감지하면, TCP는 자동으로 데이터 전송률을 줄여 네트워크 혼잡을 완화한다.
흐름 제어와 혼잡 제어는 상호 보완적으로 작용한다. 흐름 제어는 두 종단 간의 데이터 전송을 안정화하는 반면, 혼잡 제어는 네트워크 전체의 데이터 흐름을 조절하여 네트워크 혼잡을 관리합니다. 이 두 메커니즘이 조화롭게 작용함으로써 TCP는 신뢰성 높고 효율적인 데이터 전송을 제공할 수 있다.
TCP에서 세그먼트가 유실되면 타이머를 통해 유실 여부를 확인한다. 타이머 쿨타임이 차기전까지 피드백이 오지않으면 유실되었다 판단한다. 그렇다면 타이머 시간을 어느정도로 셋팅을 해야할까? 간단히 생각해보면 단순하게 RTT- Round Trip Time(한 세그먼트가 sernder에서 출발해서 reciever 로부터 ACK를 받을 때 까지 걸리는 시간) 으로 설정할 수 있다. 하지만 타이머 시간을 RTT로 설정하면 오차가 생긴다. 먼저 세그먼트 별로 RTT값이 다르다, 각 세그먼트들이 지나가는 경로가 틀리기 때문이다. 세그먼트가 지나가는 경로가 같더라도 RTT값이 틀리다. 같은 라우터를 지나가더라도 Queueing Delay 등 다양한 변수가 있기 때문입니다. 따라서 Time Out 의 시간을 정할 때는 RTT값을 보정한 값에 마진을 더한 값을 사용한다.
TCP 통신을 정리하자면 윈도우 사이즈만큼 쏟아붇는 Pipelining 방식이고, Cumulative Ack를 사용하며, 하나의 타이머를 사용한다(GBN과 유사 - 하지만 타이머 초과하면 버퍼에 있던 녀석을을 모두 재전송하는 GBN과 다르게 TCP는 타이머 초과한 녀석만 재전송)
앞서 이야기한 것중 Flow Control 과 Congestion Control을 복습해보자. TCP 데이터 통신에 있어 Receiver 데이터 처리속도가 Sender 데이터 전송 속도보다 빠른 것은 문제가 되지 않지만, Sender의 데이터 전송속도가 Receiver 의 데이터 처리속도보다 빠르면 문제가 된다. 이 문제상황에서 Receiver의 버퍼가 꽉차 데이터 유실이 발생하는데 이를 수신버퍼 오버플로우라고 부른다. 수신버퍼 오버플로우 방지를 위해 Sender 의 데이터 전송속도를 강제로 줄이게 되는데 이를 Flow Control이라 부른다.
Flow Control을 하는 구체적인 방식은 Sliding Window 이다. Sender 와 Receiver 에 각각 윈도우를 두어 받을 수 있는 데이터 양을 확인한다. 여기서 윈도우에는 두 종류가 있는데 송신윈도우(awnd) 와 수신윈도우(rwnd)이다. 송신윈도우는 sender가 ACK을 받지않아도 한 번에 연속적으로 전송할 수 있는 데이터 양, 수신윈도우는 수신자가 수신버퍼 오버플로우가 일어나지 않는 한에서 한 번에 받는 데이터를의미한다. 여기서 송신윈도우의 크기를 수신윈도우보다 작게 만들면 전송량이 수신량보다 작기 때문에 수신버퍼 오버플로우를 막는다. receiver는 수신윈도우 크기를 TCP헤서에 기록하여 sender에게 보내주면 sender는 송신윈도우를 수신윈도우보다 작세 설정한다. 이러한 Sliding WIndow 방식으로 Flow Control을 하게된다.
sender가 데이터 전송량을 과도하게 늘리면 네트워크 경로 상 라우터에는 과부하가 걸려 전송시간이 지연되거나 버퍼오버플로우가 일어나는데 이를 네트워크 혼잡이라고 한다. 이러한 라우터의 과부하를 방지하기 위해 TCP통신은 Congestion Control을 하게된다.
정리하면 TCP에서 가장 중요한 기능 세 가지를 꼽자면 reliable transfer, flow control, congestion control 이다. 지금까지 배운 위 세가지 기능은 실제 데이터 메세지가 주고받는 것이라기 보다 어떻게 TCP가 Reliable 한 연결을 보장할 수 있는지에 대한 설명이었다. 이제 실제로 어떻게 TCP 통신을 통해서 데이터를 주고 받는지에 대해 알아보자. TCP 통신은 먼저 3-way handshake 이라는 과정을 거치게 된다.
3-way handshake 이란 TCP/IP 프로토콜로 통신하기 전 정확한 정보 전송을 위해 상대방 컴퓨터와 세션을 수립하는(연결을 하는)과정이다 (TCP 연결 초기화). 구체적인 순서로는 먼저 클라이언트가 통신연결 하자고 의사표현을 한다. (기술적으로 말하자면 클라이언트가 서버에게 접속을 요청하는 SYN 패킷을 보낸다). 서버는 요청을 수락하는 의미로 받은 ACK를 포함하여 SYN+ACK 패킷을 클라이언트에게 발송한다. 클라이언트가 이것을 수신한 후 다시 ACK를 서버에게 발송하면 연결이 이루어지고 이로써 데이터를 주고 받게 된다.
전체적인 그림을 정리하자면 네트워크 연결이 시작될 때 먼저 3 way handshake 가 선행되어 클라가 서버에게 syn을 보내면 서버가 클라에게 syn+ack을 보내고 클라는 ack를 HTTP Request에 담아 보내고 서버는 HTTP Response를 보내는 순서로 진행된다. 즉 3 way handshake 의 마지막 ack에는 데이터가 담겨서 보내지게 된다. (3번째 과정의 ack이 되돌아 올때까지 클라와 서버는 buffer를 만들지 않음)
프로세스간 통신을 그만두고 싶다면 TCP연결도 끊는 작업이 필요하다. tcp 연결을 종료하는 Connection termination 과정은 4-way handshaking을 통해 이루어진다.
- Client process에서 active close를 하면, client tcp에서 FIN 세그먼트를 보낸다
- Server는 FIN 세그먼트를 받았다는 응답에 대해 ACK를 client로 보낸다.
- Server process 는 passive close 를 보내고 다시 찐으로 닫았다고 FIN 세그먼트를 client TCP에게 보낸다.
- Client tcp가 Fin을 받고 다시 서버로 ACK를 보내고 서버가 받으면 연결이 종료
자 지금까지 TCP 통신의 시작과 끝을 알아보았다. 그렇다면 이제 데이터가 어떻게 주고받는지 알아보자. 먼저 클라는 서버에게 얼마나 많이, 얼마나 빠르게 데이터를 보내주어야할까? 앞서 알아본 것과 같이 Sender 가 보내는 Segment 의 양과 속도는 Flow control 과 Congetion Control에 의해 조절된다. (이때 Flow control은 버퍼의 용량 그리고 Congetion Control는 네트워크가 감당할 수 있는 세그먼트의 양). 보내는 Segment 의 양과 속도는 버퍼의 용량과 네트워크가 담당할 수 있는 양 중 더 열악한 조건에 맞추게 된다.(TCP는 reliable 해야하기 때문에 유실되는 것 만큼은 막아야함). 따라서 Sender에서 segment를 보낼 때 알맞은 양과 속도를 맞추려면 끊임없이 버퍼와 네트워크를 체크해야한다.
패킷들이 fluid고 통신링크를 파이프라고 했을 때 파이프라인에 물을 부어서 나오는 물을 마신다. 여기서 고려해야할 사항은 가장 얇은 파이프라인이다. 얇은 파이프라인이 터지지 않을정도로 물을 부어야하기 때문이다. 이렇게 가장 사고 터지기 쉬운 파이프를 어떻게 탐지할 수 있을까? 바로 조금씩 물을 흘려보내면서 점차 물을 많이 보내며 전송률에 변화가 있는지 체크함으로써 병목현상을 탐지한다. 이러한 과정이 TCP Congestion control 이 하는 일이다.
TCP Congestion Control은 세가지 main phases 를 통해 진행된다.
- Slow Start: 먼저 조금조금씩 데이터를 보내서 네트워크가 얼마나 견딜 수 있는지 체크한다.
- Addictive increase: 예를들어 1,2,3,4 씩 보내는데 네트워크가 받아들일 수 있는 양이 10,000 이면 체크하는데 너무 시간이 오래걸릴 수 있다. 이를 방지하기 위해 데이터를 보내는 양을 2배씩 증가시킨다.
- Multiplicative Decrease: 이렇게 데이터를 늘려가며 네트워크를 가늠할 때 만약 패킷유실이 감지되면 바로 보내는 데이터의 양을 반절로 줄여버린다.
위에서 보았듯이 어쩔 수 없이 패킷 유실 (Packet Loss) 가 발생할 수 밖에 없다. 그렇다면 Congetion Control은 어떻게 탐지할 수 있을까? 두가지 방법으로 Packet Loss 를 탐지한다. time out 과 3 duplicate ACK이다. 이때 duplicate ACK는 특정 패킷이 유실되고 나머지는 잘 전달된데에 반해서 time out은 아예 패킷들이 모두 전달이 안되어 더 심각한 상황이라 볼 수 있다. 이에 대응하기위해 duplicate ACK에서는 윈도우 사이즈를 절반만 줄이고 다시 linear increase를 합니다 이를 TCP Reno 라고 한다. time out 에 의한 패킷유실이었다는 것이 판단되면 아예 처음부터 다시 slow start를 시도한다 이를 TCP Tahoe 라고 한다.
위와 같은 TCP Congestion Control 메커니즘은 TCP Connection이 여러개 들어오더라도 자원을 공평하게 나눠가질 수 있도록 도와준다. 위표를 보면 알 수 있듯이 x축은 connection1이 가질 수 있는 네트워크 자원, y축은 connection 2가 가질 수 있는 네트워크 자원으로 connection들은 fair하게 네트워크 자원이 분산된다.
TCP는 Go-Back-N과 Selective Repeat의 몇몇 특성을 차용했다.그렇다면 SR과 TCP의 cumulative ack의 차이점은 무엇일까?
Cumulative ACK은 수신된 모든 연속된 패킷을 확인하고, 가장 마지막으로 정상적으로 받은 패킷의 번호를 송신자에게 알려준다. 예를 들어, 패킷 1, 2, 3, 4를 받아야 하는데 3번 패킷이 유실된 경우, 수신자는 2번 패킷까지만 받았다고 2번 ACK을 송신자에게 계속 보내게 된다. 유실된 패킷 이후에 도착하는 패킷들은 버퍼에 저장하며, 이들에 대한 별도의 ACK은 보내지 않는다. 이후 유실된 패킷이 재전송되어 올바르게 수신되면, 그 때 버퍼에 저장된 이후 패킷들을 함께 처리하고, 가장 마지막 패킷의 번호로 ACK을 보낸다.
Selective Repeat 방식은 각각의 개별 패킷에 대해 독립적인 ACK을 보낸다. 만약 패킷 1, 2, 3, 4를 받아야 하고 3번 패킷이 유실되면, 1번과 2번 패킷에 대한 ACK은 보내지만 3번에 대해서는 보내지 않고, 4번 패킷이 도착하면 4번에 대한 ACK도 보낸다. 유실된 패킷과 무관하게 각 패킷에 대해 독립적인 ACK을 보냄으로써, 각 패킷의 도착 상태를 더 정확히 관리할 수 있다. 하지만 메모리 효율성을 위해 TCP통신은 Cumulative ACK을 채택했다. 따라서 duplicate ACK은 Selective Repeat 이 아닌 Cumulative ACK으로부터 온다.→ Fast Retransmit 은 Slective Repeat 때문이 아닌 Cumulative ACK 때문에 가능함
Fast Retransmit은 TCP 네트워킹 프로토콜에서 패킷 손실을 빠르게 감지하고 해결하는 기능이다. 패킷 손실이 일어날 때까지 기다리는 대신, 빠른 감지와 재전송을 통해 네트워크 성능을 최적화한다. (타이머가 있기 때문에 Fast Retransmit 이 필수는 아니다)
- 패킷 송신과 수신: 송신자는 여러 개의 패킷(예를 들어 1, 2, 3, 4번)을 연속적으로 보낸다.
- 패킷 손실 발생: 만약 3번 패킷이 중간에 손실되면, 수신자는 2번 패킷까지만 정상적으로 받았다는 의미로 2번 ACK(수신 확인 응답)을 보낸다.
- 중복 ACK 수신: 송신자가 4번 패킷을 계속 보내더라도 수신자는 여전히 2번 패킷까지만 받았다고 2번 ACK을 반복해서 보냅니다. 이러한 중복 ACK이 3번 이상 발생하면,
- Fast Retransmit 발동: 송신자는 타이머가 만료되기를 기다리지 않고 즉시 3번 패킷을 재전송한다. 이는 타이머를 사용하여 재전송하는 기존 방식보다 훨씬 빨라진다.
'Computer Science > Network' 카테고리의 다른 글
무선 이동 네트워크 (0) | 2024.05.20 |
---|---|
링크 계층 (2) | 2024.05.14 |
네트워크 계층 (0) | 2024.05.09 |
| 컴퓨터 네트워킹 하향식 접근 | Ch1 컴퓨터 네트워크와 인터넷 (0) | 2024.05.07 |