Connecting

Chapter 02 TCP/IP Packet Transmission - 1 본문

네트워크

Chapter 02 TCP/IP Packet Transmission - 1

팬도라 2018. 11. 16. 17:51
반응형


Chapter 02 TCP/IP Packet Transmission - 1

  • 프로토콜 스택에 대한 전반적인 내용을 습득합니다.

  • NIC통신 과정에 대해 살펴봅니다.

  • IP패킷 및 UDP 프로토콜을 이용한 송/수신 동작을 살펴봅니다.

프로토콜 스택

  • 프로토콜 스택은 역할이 서로 다른 몇 부분으로 나뉘어져 있습니다.

  • 상위계층인 Application Layer(네트워크 애플리케이션)의 경우 브라우저, 웹 서버, 메일 서버 등의 프로그램이 해당됩니다.

  • 애플리케이션 하위계층에는 Socket 라이브러리가 있으며 이 안에는 저번시간에 설명한 Resolver가 포함되어 있습니다.

  • 다음 하위계층에 OS에 내부에 프로토콜 스택이 존재합니다.

    • 프로토콜 스택의 윗부분에 TCP, UDP와 같이 데이터 송 수신을 담당하는 부분이 있습니다.

    • 이는 애플리케이션에서 필요하는 데이터를 송수신하는 역할을 담당합니다.

  • IP의 경우 패킷이라는 데이터 형식을 통해서 상대방까지 데이터를 운반하는 역할을 담당하게 됩니다.

    • IP 안에는 ICMP(패킷을 전송할 때 발생하는 오류를 및 제어용 메시지를 통지하는 역할), ARP(IP 주소에 대응하는 MAC 주소를 조사할 때 사용)가 있습니다.

  • 마지막의 존재하는 PHY 계층의 경우 NIC가 실제로 전기적인 신호로 케이블을 사용하여 데이터를 송수신하는 역할을 담당합니다.

소켓(Socket)의 실체

  • 이제 소켓(Socket)에 대해서 알아보도록 하겠습니다.

  • 프로토콜 스택 내부에는 제어정보를 기록하는 메모리 영역을 가지고 있으며, 여기에 통신 동작을 제어하기 위한 제어정보를 기록합니다.

    • 상대방의 IP

    • 포트번호

    • 통신 동작 상태

  • Socket은 개념적인 부분이므로 이러한 제어정보를 기록한 메모리 영역이 소켓이라고 지칭할 수 있습니다.

  • 프로토콜 스택은 이 정보를 활용하여 실질적으로 데이터를 송수신하기 위한 절차들이 이루어지며, Socket에 기록된 여러가지 제어 정보를 참조하여 다음 행위를 진행합니다.

  • 실질적으로 통신이 이루어지기 위해서는 Socket을 만들어야 합니다.

  • 프로토콜 스택은 의뢰받은 요청에 따라 Socket을 만들기 전에 메모리 영역을 할당하여 제어정보를 담을 공간을 확보합니다.

  • 이후 Socket을 나타내는 디스크립터를 애플리케이션에게 전달하여, 다수의 Socket 중 어느 것을 가리키는지 알 수 있게 됩니다.

  • 이렇게 디스크립터가 Socket을 가리키게 되면 모든 정보는 Socket에 기록되어 있기 때문에 상대방의 정보를 애플리케이션에서 일일히 통지받을 필요가 없습니다.

접속(Connection)

  • 이더넷이나 통신회선은 항상 연결되어 있기 때문에 언제나 신호를 받을 수 있습니다.

  • 하지만, Socket을 만든 직후에 애플리케이션에서 데이터 송신 의뢰가 오면, 메모리에 어떠한 정보도 기록되어 있지 않기 때문에 통신상대를 알 수 없습니다.

  • 이러한 문제를 해결하기 위해 접속을 위해서는 통신 상대와의 제어 정보를 주고 받아 Socket에 필요한 정보를 기록하고 데이터 송수신이 가능한 상태로 만들어주는 작업이 필요합니다.

    • 헤더 정보를 확인하면 좀 더 명확하게 알 수 있습니다.

    • 전송하고자 하는 데이터가 TCP 영역에 도착하면, 송신처와 수신처의 포트번호를 기입합니다. 이를 통해 서버측과 클라Socket을 지정하는 첫번째 단계가 진행됩니다.

    • 접속해야 하는 Socket을 확실하게 정해지게 되면 Sequence Number(SYN) 컨트롤 비트를 1로 만듭니다.

  • 이렇게 만들어진 TCP 헤더는 IP에 전달하여 송신할 수 있도록 의뢰하는 작업이 이루어지고, 패킷이 정상적으로 서버에 도착했을 경우 서버의 TCP가 헤더정보를 조사하여 수신 포트번호에 해당하는 Socket을 찾아냅니다.

  • 클라이언트와 마찬가지로 헤더를 설정하고 Acknowloedgment Number(ACK) 컨트롤 비트를 1로 만들로 전송합니다.

    • 이는 어떠한 이유로 오류가 발생하여 패킷이 손실되어 수신받지 못하는 상황을 대비하기 위함입니다.

  • 클라이언트가 이러한 정보를 정상적으로 수신받았다면, TCP 헤더를 조사하여 SYN 비트가 1인지 확인하고 접속을 완료하는 동시에 서버측으로 ACK 비트를 1로 설정하여 전송합니다.

    • 이는 서버측에서 보낸 정보가 정상적으로 도착했다는 것을 서버에 알려주기 위함입니다.

  • 이러한 동작이 완료되면 데이터를 송수신할 수 있는 상태가 되며, 커넥션이 완료되었다고 표현합니다.

데이터 송수신

  • 프로토콜 스택은 받은 데이터를 바로 전송하지 않고 송신용 버퍼 메모리 영역에 저장하고, 애플리케이션이 다음 데이터를 건네주기를 기다립니다.

    • 송신시 애플리케이션에서 건네주는 데이터의 길이는 애플리케이션의 종류나 만드는 방법에 따라 다르기 때문입니다.

    • 또한 받은 데이터를 곧바로 보내게 되면 작은 데이터를 많이 보내게 되며, 이는 네트워크 이용 효율의 저하로 나타납니다.

    • 네트워크에서 최대로 보낼 수 있는 패킷의 사이즈는 MTU를 기반으로 판단하며, 보통 1,500byte가 됩니다.

    • 이 때, MTU 맨 앞 부분에는 헤더가 포함되어 있기 때문에 헤더를 제외한 부분이 하나의 패킷으로 전송할 수 있는 최대 길이 MSS(헤더를 제외하고 한 개의 패킷으로 운반할 수 있는 TCP의 데이터의 최대 길이)가 됩니다.

    • 애플리케이션에서 데이터가 MSS를 초과하거나 MSS에 가까운 길이에 이르기까지 데이터를 저장하고 송신동작을 하면 길이 맞춰서 잘라서 보내기 때문에 이후 동작에 대해서는 신경쓰지 않아도 됩니다.

  • 또 하나로 애플리케이션의 송신 속도가 느려지는 경우 MSS에 가깝게 데이터를 저장하면 지연시간이 발생하기 때문에 버퍼에 데이터가 모이지 않더라도 적당한 시간이 경과하면 패킷을 송신합니다.

  • TCP에는 송신한 패킷이 상대에게 올바르게 도착했는지 확인하고, 도착하지 않았을 경우 재송신하는 기능이 있습니다.

    • TCP에서 데이터를 분할할 시 조각이 통신 개시부터 따져서 몇 번째 바이트에 해당하는지 세어둡니다.

    • 이 데이터 조각을 송신할 때 세어둔 값을 TCP 헤더에 기록하는데, 이것이 시퀀스 번호가 됩니다.

    • 송신측에서는 패킷의 전체 길이에서 헤더의 길이를 빼면 데이터의 크기를 알 수 있으므로, 수신측에서는 이 방법에 따라 크기를 산출합니다.

    • 이렇게 수신측에서 데이터가 누락되었는지 확인할 수 있으며, 누락값이 있을 경우 이전에 수신받은 데이터의 길이를 확인하여 TCP 헤더에 기록하여 송신측에 전송합니다.

    • 이렇게 송신 -> 확인 -> 응답에 대한 동작은 수신 확인 응답이라고 하며, 송신측은 이것을 통해 상대가 어디까지 수신했는지를 알 수 있습니다.

  • 시퀀스 번호는 난수를 바탕으로 산출되는데, 이는 고정값으로 사용할 경우 해킹을 할 수 있기 때문입니다.

  • 따라서 초기값을 사전에 상대에게 알려주어야 하며, 이를 위해 SYN 제어비트를 1로 설정하여 초기값을 통지합니다.

  • 이러한 TCP의 특성 덕분에 네트워크의 오류가 발생하더라도, 오류를 검출하여 회복할 수 있습니다.

    • 단, 통신 도중에 케이블이 분리되거나, 서버가 다운되는 등의 이유로 TCP가 해결할 수 없는 물리적인 이유로 인해서 통신이 불가능한 경우에도 계속해서 패킷을 전송하면 문제가 발생하기 때문에 응답이 없을 경우 회복 불가능이라고 판단하고, 애플리케이션에 오류를 통지합니다.

패킷 왕복시간을 통한 대기시간 계산
  • 네트워크가 혼잡하여 정채가 일어나면 ACK 번호가 돌아오는 것이 지연되기 때문에 이것을 예측하여 적절한 대기시간을 설정해야 합니다. 이 대기시간을 타임아웃 값이라고 합니다.

  • 하지만 이러한 대기시간은 서버와의 거리, 네트워크 혼잡 등 다양한 이유로 인해서 달라질 수 있기 때문에 대기시간을 일정한 값으로 설정하는 것은 적절하지 않습니다.

    • 이러한 문제를 해결하기 위해서 TCP는 ACK 번호가 돌아오는 시간을 기준으로 동적으로 대기시간을 변경합니다.

    • 이를 통해 데이터 송수신이 이루어 지는 동안 ACK가 지연되면 대기 시간을 지연시키고, ACK가 바로 들어오면 대기 시간을 짧게 설정합니다.

윈도우 제어
  • 한개의 패킷을 보내고 ACK 번호를 기다리는 방법은 단순하지만, 그 시간동안 아무것도 하지 않는건 시간낭비입니다.

  • 따라서 window congestion을 통해서 한 개의 패킷을 보내고 ACK 번호를 기다리지 않고 차례대로 복수의 패킷을 전송하는 방법을 사용합니다.

  • 단, ACK 번호를 기다리지 않고 차례로 패킷을 보내면 수신측의 능력을 초과하여 패킷을 보내는 사태가 일어날 수 있습니다.

    • TCP는 패킷을 수신하면 버퍼에 내용을 저장하는데, 수신측에서 ACK 번호를 계산하거나, 여러 패킷을 복원하여 애플리케이션으로 전달해야 합니다.

    • 이때, 처리가 끝나지 않은 상태에서 계속해서 데이터가 들어오면 수신버퍼에 데이터가 가득차고, 이후에 들어오는 데이터는 사라지기 때문에 오류가 발생하게 됩니다.

    • 이러한 문제를 해결하기 위해서 수신측에서 자신의 버퍼의 용량을 알려주고, 송신측은 데이터를 전송함에 있어서 수신측의 메모리 영역을 계산하게 됩니다.

    • 수신측의 버퍼메모리의 공간이 없으면, 송신을 중단하고, 수신측에서 데이터를 처리한 다음에 비어진 영역만큼의 공간을 송신측의 통보함으로서 수신측의 능력을 초과하여 데이터를 보내는 일이 없도록 합니다.

    • 이렇게 수신 가능한 데이터 양의 최대값을 윈도우 사이즈라고 하며, TCP를 조정하는 매개변수의 하나입니다.

  • 수신측에서 ACK번호를 바로 통지하는 것은 수신측에서 송신측에 보내는 패킷이 많이지기 때문에 효율성이 떨어집니다.

    • 수신한 데이터의 끝이 어디인지를 알리는 것이 ACK의 역할 이므로 ACK 번호 통지가 연속적으로 일어나면 최후의 것만 통지하고 도중의 것은 생략하여 패킷을 줄일 수 있습니다.

TCP 연결 종료

  • 송수신을 종료한다는 것은 애플리케이션이 송신해야 하는 데이터를 전부 송신 완료했다고 판단했을 때 입니다.

  • 따라서 데이터를 보낸 쪽에서 연결을 종료하기 위해서 TCP헤더에 FIN을 1로 설정한 패킷을 전송합니다.

  • 이를 수신한 클라이언트는 정상적으로 패킷을 수신했다는 ACK를 반송하여 종료동작이 완료됩니다.

  • 이러한 동작이 정상적으로 이루어지기 위해서 소켓을 바로 종료하지 않고 보통 몇 분 정도의 시간이 지다고 말소하게 됩니다.

    • 소켓을 바로 말소하지 않는 이유는 어떠한 이유로 발생할 수 있는 오동작을 막기 위함입니다.


Comments