오늘은 TCP Segment 송수신 원리에 대해 알아보겠습니다.

 

클라이언트와 서버 간 서로 통신을 위해 TCP로 연결 된 모습을 간략하게 나타낸 그림입니다.

TCP 프로토콜로 연결하기 전, 3-way handshake 과정은 다음번에 더 자세히 다루도록 하겠습니당.

간단하게 설명하자면 3-way handshake는 클라이언트와 서버 간 데이터를 주고 받기 전에 서로간의 연결 상태(SYN, ACK)를 확인하는 과정을 말합니다.

먼저, 위 그림 같은 상황에서 서버가 클라이언트로 응답 데이터를 보낼때 서버에서 일어나는 상황을 볼까요 ?

 

서버의 프로세스에서 클라이언트 쪽으로 하드웨어 영역에 있는 파일을 전송한다 가정했을 때, 서버 쪽 프로세스는 해당 파일을 처리하기 위해 메모리에 적재를 합니다.

하드웨어 영역의 파일은 커널의 파일 시스템에 의해 관리되며, 하드 디스크는 소프트웨어 영역의 하드 디스크 드라이버에 의해 관리되겠죠.

 

이 때, 할당되는 메모리가 전송하려는 파일 크기보다 작다면, 할당된 메모리 크기에 맞춰 파일을 분할하여 메모리에 적재하게 됩니다.

(메모리만 받쳐준다면...많이 적재하는게 좋긴 하겠죠 ..ㅎㅎ) 

 

바로 아래 그림과 같이 말이죠.

전송하려는 파일 크기는 1.4MB, 할당된 메모리는 64KB이며 64KB 단위로 분할

이후, 서버 측 프로세스에선 데이터를 전송하기 위해 TCP/IP 프로토콜 스택에서 TCP Buffer에 현재 메모리에 적재되어 있는 분할된 데이터를 담게 됩니다. 

분할된 데이터가 메모리에서 TCP Buffer로 카피된다고 볼 수 있죠.

이 과정을 Buffered I/O라고 부릅니다.

 

TCP 버퍼에 카피된 데이터가 Internet 계층으로 인캡슐레이션 과정이 일어나게 되고, 이 과정에서 데이터가 세그먼트로 분할 되며 , 각각의 세그먼트들에게는 번호가 부여되게 됩니다. ( 예시 : 1번 세그먼트 + 2번 세그먼트 + 3번 세그먼트 = 보내려는 데이터 )

응답 서버 측 입장에선 4-3-2-1 순으로 패킷이 인캡슐레이션 된다.

분할된 세그먼트를 순서대로 패킷에 담아 스위치와 라우터 등을 거쳐 클라이언트 쪽으로 전송하게 됩니다. 

 

이 때, 당연히 해당 패킷에는 목적지 주소 정보도 같이 포함되어 있습니다.

 

성공적으로 패킷이 클라이언트 측으로 도착하면, 인캡슐레이션 된 패킷을 디캡슐레이션을 하게 됩니다. (택배 상자가 오면 하나하나 까듯이요 )

  1. 클라이언트 측 Internet 레이어 수준에서 패킷을 분해합니다. 
  2. 클라이언트 측 Transport 레이어 수준에서 세그먼트를 확인합니다.

클라이언트 측 OS 모델

서버 측에서 분할된 세그먼트는 다시 클라이언트 측 TCP 버퍼에 그대로 적재되게 됩니다. 

 

예시 상황으로 위 과정을 다시 쉽게 설명드리자면

  1. 서버 측에서 분할된 데이터 ( 1, 2번 세그먼트) 를 패킷에 적재합니다.
  2. 해당 패킷에 목적지 주소 정보와 포트 번호를 함께 붙입니다.
  3. 서버 -> 클라이언트로 패킷을 전송 후, 클라이언트에선 다시 패킷을 분해해 클라이언트의 TCP/IP 프로토콜 스택 상위 계층으로 올려보냅니다.
  4. 클라이언트 측은 1,2번 세그먼트를 성공적으로 받았다는 응답 (ACK)을 서버측으로 보내게 됩니다.

그 이후 서버 측에서 만약 더 보내야할 데이터가 있을 경우에는 위의 4번 과정의 ACK를 Wait하게 됩니다.

 

(왜냐하면 1, 2번 세그먼트를 클라이언트에서 성공적으로 받았다는 응답이 있어야 3번 세그먼트를 전송할 수 있기 때문이지요)

 

여기서 중요한건, 위의 4번 과정에서 서버 측으로 ACK를 보낼 때, 현재 TCP Buffer에서 남아있는 공간 ( Window Size)도 같이 전송하게 됩니다. (수신의 경우 버퍼는 OS에서 관리하는 수신 버퍼를 사용합니다)

클라이언트 측의 세그먼트를 처리할 수 있는 공간이 얼마 남았다, 라는 것을 보내준다는 의미라고 생각하시면 됩니다.

 

여기서 클라이언트의 ACK( 1, 2번 세그먼트 잘 받았어 3번 보내줘) 응답을 받은 서버는 3번 세그먼트를 보내기 전, 클라이언트의 윈도우 사이즈를 확인하고, 보낼지 말지 결정하게 됩니다.

 

만약, 보내려는 세그먼트 사이즈가 클라이언트 측의 윈도우 사이즈 보다 작으면 당연히 보내게 되는데, 이 반대의 상황이라면

Wait가 걸려버리게 됩니다.

여기서 서버측의 Wait가 발생하는 상황은 여러가지가 있을 수 있겠지만,

이 경우에서는 클라이언트 측의 파일 처리 속도가 네트워크 데이터를 수신하는 속도보다 느릴 경우, 클라이언트 측의 충분한 버퍼 사이즈가 확보되지 않아 발생할 수 있습니다.

그래서 보통 클라이언트 측에서는 데이터를 읽자마자 처리 루틴을 별도 스레드로 분리해 대응한다고 합니다.

만약 데이터를 읽고 처리하는 코드를 한 스레드 안에 묶어버리면 위와 같이 장애 가능성이 매우 높아집니다.

 

여기까지 서버와 클라이언트 측의 데이터가 어떤 식으로 전송되는지 알아보았습니다 !

 

ref : https://youtu.be/K9L9YZhEjC0?si=vMtodPcxR6AAQLdS

'Network' 카테고리의 다른 글

3-way handshake  (1) 2023.11.07
DHCP ? (Dynamic Host Configuration Protocol)  (5) 2023.08.09

+ Recent posts