Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

TCP의 신뢰성은 어떻게 보장하는가? #97

Open
inuinseoul opened this issue Feb 10, 2022 · 4 comments
Open

TCP의 신뢰성은 어떻게 보장하는가? #97

inuinseoul opened this issue Feb 10, 2022 · 4 comments
Labels

Comments

@inuinseoul
Copy link
Collaborator

No description provided.

@sustainable-git
Copy link
Member

  • TCP는 자신이 보낸 Data에 대해 상대방이 받았다는 응답 packet을 받아야 합니다. 그렇지 않으면, packet이 유실되었다고 판단하고 다시 보냅니다.
  • TCP는 Header의 Checksum을 이용해 오류를 확인하는데, Data가 잘 보내 졌다면 ACK Flag를 1으로, 그렇지 않으면 0으로 보냅니다. 또한 Sequence Number를 이용하여 순서를 보장하기 때문에 신뢰성이 보장됩니다.

@tmfrlrkvlek
Copy link
Collaborator

TCP는 재전송을 통해 신뢰성을 보장합니다. TCP Header의 Checksum 부분을 사용하여 데이터가 정상적으로 수신되었는지 확인합니다.
송신자는 TCP Header를 16bit로 잘라 1의 보수의 합을 Checksum에 저장해둡니다. 수신자는 이 Checksum 값이 이상할 경우 TCP Flag 중 ACK Flag를 0으로 Set하여 보냅니다. 반대로 제대로 왔을 경우 ACK Flag를 1로 Set하고 수신자가 받은 Seq Number에서 1을 더한 값을 Acknowledgement number에 넣어 보냅니다.
데이터의 순서는 수신자 측에서 Seq Number 순서대로 데이터를 붙임으로써 보장할 수 있습니다.
마지막으로 수신자가 ACK/NACK조차 보내지 못하거나 해당 메시지가 누락된 경우, 일정 시간이 지나면 timeout 처리되어 해당 데이터를 재전송합니다.

@duyeonnn
Copy link
Collaborator

TCP는 특성상 자신이 보낸 데이터에 대해서 상대방이 받았다는 의미의 패킷을 다시 받아야 통신이 정상적으로 이뤄졌다고 생각한다.

그래서 만약 자신이 보낸 데이터에 대해 응답 패킷을 받지 못한다면, 패킷이 유실되었다 생각하고 보냈던 패킷을 다시 보내게 됩니다. 이 과정을 TCP 재전송이라 합니다.

TCP 재전송은 보냈던 패킷을 다시한번 보내기 때문에 네트워크 성능 저하를 일으킬 수 있지만 TCP 통신상 반드시 필요한 과정이다.

수신자가 TCP Segment에 오류가 있는지 확인하는 방법은 TCP Segment의 Header부분중 Checksum 부분을 보고 알 수 있다.

이 Checksum Error Detecting을 통해 수신자는 송신자가 보낸 데이터가 제대로 보내졌는지 확인 할 수 있으며 잘못보내졌을 경우 위 TCP Flag 중에서 ACK Flag를 reset(0)하여 보냅니다. 제대로 보내졌을 경우에는 ACK Flag를 set(1)하고 Acknowlegment number에 수신자가 받았던 sequence number에 1을 더한 sequence number+1의 값을 넣어서 보내줍니다.

순서가 뒤바뀐 TCP Segment의 경우도 Sequence number가 있기 때문에 수신자 측에서 이러한 Sequence number순서대로 데이터 청크(Data chunks)들을 잘 붙여주기만 하면 된다.

만약 수신자가 송신자에게 ACK, NAK 둘다 못보내는 상황이라면 timeout 개념을 사용합니다. 일정 시간동안 ACK또는 NAK가 오지 않는다면 timeout된 시점에서 다시 TCP Segment를 보내주게 됩니다. timeout 주기를 너무 길게 생성하면 퍼포먼스의 하락을 가져오고 너무 짧게 설정해도 계속 다시 쓰기 떄문에 역시 퍼포먼스의 하락을 가져옵니다.

@inuinseoul
Copy link
Collaborator Author

네트워크 통신과정 도중에는 네트워크 혼잡성 및 receiver의 overload 등의 사유로 데이터가 손실되거나, 전달 순서가 바뀌는 등의 문제가 발생할 수 있습니다. 이런 문제를 해결하고 통신의 신뢰성을 보장하기 위해 TCP/IP에서 사용하는 것이 흐름 제어와 혼잡 제어입니다.

  • cf. TCP 버퍼 : 전송 및 수신 전 TCP 세그먼트는 보관하는 곳입니다. 송신 측은 버퍼에 TCP 세그먼트를 보관한 후 순차적으로 전송하고, 수신 측은 도착한 TCP 세그먼트를 애플리케이션이 읽을 때까지 버퍼에 보관합니다. 이 크기에 너무 작으면 당연히 손실되는 데이터가 많아지겠죠?

흐름 제어

수신 측이 송신 측보다 데이터 처리 속도가 느릴 경우 데이터를 손실할 위험이 존재합니다. 흐름 제어는 이런 송신 측과 수신 측의 데이터 처리 속도 차이로 인해 발생하는 문제를 해결하기 위한 기법입니다.
 
이를 실현하기 위한 방법으로는 Stop and Wait, Sliding Windoew가 있습니다.

  • Stop and Wait : 매번 전송한 패킷에 대해 응답(ACK)을 받으면 다음 패킷을 전송하는 기법입니다. 이는 패킷을 하나씩 보내고 확인해야 하기 때문에 비효율적입니다.
  • Sliding Window : 수신 측에서 설정한 '윈도우'의 크기만큼 송신 측에서 패킷을 전송하도록 하여 데이터의 흐름을 동적으로 조절하는 기법입니다. 최초 윈도의 크기는 3way-handshaking 과정을 통해 설정되며, 이후 수신측에서 버퍼의 공간에 따라 변경합니다. ('윈도우'값은 TCP header에 존재하고 관리됩니다.) 윈도우에 포함된만큼은 수신 측의 응답(ACK)없이도 보낼 수 있지만, 그 이상은 보낼 수 없습니다. 그 이상의 데이터 패킷을 보내기 위해서는 수신의 응답(ACK)가 확인되어 다시 윈도우의 크기가 갱신되어야 합니다.

혼잡 제어

데이터의 양이 라우터가 처리할 수 있는 양을 초과하면 라우터는 더 이상 데이터를 처리할 수 없습니다. 이런 상황에서 송신 측은 라우터에서 처리하지 못한 데이터를 손실 데이터로 간주하고 계속해서 데이터를 전송하게 됩니다. 이는 네트워크를 혼잡하게 만듭니다. 혼잡 제어는 이런 네트워크의 혼잡성 문제를 해결하기 위한 기법입니다.
 
흐름제어가 송 수신측의 패킷 수를 제어하는 기법이라면, 혼잡제어는 네트워크 내의 패킷 수를 제어하는 기법이라고 할 수 있겠네요.
 
이를 실현하기 위한 방법으로는 AMD, Slow Start가 있습니다.

  • AIMD : Additive Increase & Multicative Decrease의 약자로, 합 증가 & 곱 감소라는 의미입니다. 처음에 패킷을 하나씩만 보내고 문제없이 해당 패킷이 도착하면 윈도의 크기를 증가시켜 전송합니다. 만약 전송 실패가 발생할 경우 윈도우의 크기를 반으로 줄입니다. 윈도우의 크기를 너무 조금씩 늘리기 때문에 네트워크의 대역을 제대로 활용하여 속도를 내기엔 시간이 걸린다는 단점이 있습니다.
  • Slow Start : 윈도우의 크기를 지수적으로 증가하다가 혼잡이 감지되면 1로 줄이는 방법입니다. 윈도우의 크기가 처음에는 조금 느리게 증가하지만, 시간이 지날수록 윈도우의 크기가 빠르게 증가한다는 장점이 있습니다.
    AIMD, Slow Start를 사용하면서 네트워크의 혼잡이 자주 발생하면 윈도우의 크기가 크게 감소하고 네트워크의 전송률이 매우 떨어집니다. 따라서 TCP에는 패킷을 재전송하는 기법들이 존재합니다. 이들 역시 혼잡제어 기법의 일종입니다.
  • Fast Retransmit : 수신 측은 먼저 도착해야하는 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 응답(ACK)를 보냅니다. 단, 순서대로 도착한 마지막 패킷의 다음 패킷 순번을 응답 패킷에 실어서 보내기 때문에 송신 측은 순번이 중복된 응답 패킷을 받게되고, 이러한 중복 패킷을 3번 감지하면 문제가 되는 순번의 패킷을 재전송해줄 수 있습니다.
  • Fast Recovery : 혼잡한 상태가 되면 윈도우의 크기를 1로 줄이지않고 반으로 줄인 다음 선형적으로 증가시키는 기법입니다. 이 기법을 적용하면 혼잡상황을 겪고난 후에는 AIMD와 같은 방식으로 동작합니다.

실질적인 혼잡제어는 이 중 하나만으로 작동한다기보단, 상황에 따라 정책을 바꿔가며 제어합니다. 예를 들면 처음에는 Slow Start를 사용하다가 이런 정책에는 Tahoe, Reno, New Reno, Cubic, Ealstic-TCP 등 여러가지가 존재합니다.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants