본 내용은 유튜브 널널한 개발자 TV 채널을 보고 정리한 것입니다.
이해하면 인생이 바뀌는 TCP 송/수신 원리
웹 서버는 소켓을 통해 클라이언트와 통신한다.
프로세스가 소켓 파일에 대해 기본적으로 할 수 있는 기능은 rwx가 있다.
r(read): 읽기
w(write): 쓰기
x(execute): 실행
먼저 클라이언트가 웹 서버에게 A 파일을 요청해서 웹 서버가 해당 데이터를 전달해주는 과정을 생각해보자.
제일 먼저 웹 서버는 하드디스크로부터 A 파일을 읽어들인다.
웹 서버의 프로세스-소켓 수준에는 할당되어 있는 버퍼메모리가 있다.
(메모리의 크기는 개발자가 결정한다.)
버퍼메모리의 크기는 A 파일의 전체 크기보다 작고, 버퍼메모리의 크기에 맞게 A 파일을 분할해서 하나씩 읽어들인다.
웹 서버의 프로세스가 하드디스크로부터 A 파일을 모두 읽어들인 뒤, 다시 하위 계층으로 보내면서 클라이언트의 프로세스로 A 파일 데이터가 전달된다.
하위 계층인 TCP 수준의 버퍼메모리에 옮겨질 때에 데이터는 세그먼트 단위로 쪼개진다. 세그먼트 단위로 쪼개질 때에는 하나의 세그먼트마다 일련번호가 붙게 된다.
다음 하위 계층인 IP 수준으로 내려오면서 데이터는 패킷 단위가 된다.
또 다음 하위 계층인 NIC 수준으로 내려오면서 데이터는 프레임 단위가 된다.
세그먼트 = 내용물, 패킷 = 택배상자, 프레임 = 택배트럭으로 생각하자.
하나의 프레임씩 클라이언트 측으로 전달되면서 이번에는 반대로 하위계층에서부터 상위계층으로 데이터가 전달된다.
웹 서버에서 진행됐던 순서가 반대가 되면서 프레임 -> 패킷 -> 세그먼트 순서로 데이터가 다시 분리되고, 세그먼트는 하나씩 클라이언트의 TCP 메모리에 쌓이게 된다.
보통 세그먼트 2개 정도가 쌓이면 '수신측'에서 '송신측'으로 ACK 3번 신호를 보낸다. 송신측은 해당 신호를 받으면 '수신측이 1~2번 세그먼트까지 잘 받았구나, 이어서 3번 세그먼트를 보내면 되겠구나' 라고 판단한다.
송신측은 수신측으로부터 ACK 신호를 받을 때까지 기다리고 있는데, 이 기다리는 시간 때문에 속도 지연이 발생한다.
특히 중요한 것이 하나 더 있다.
수신측의 TCP 버퍼에 남아있는 메모리 크기를 Window size 라고 하는데, ACK 신호를 보낼 때 이 윈도우 사이즈 정보도 같이 보낸다.
송신측은 ACK 신호를 받은 뒤, 윈도우 사이즈를 보고 3번 세그먼트를 보낼지 말지 판단한다.
수신측의 윈도우 사이즈가 보내려는 세그먼트의 MSS(Maximum Segment Size)보다 크면 보내고, 작다면 보내지 않는다.
윈도우 사이즈가 MSS보다 작다는 것은 수신측에서 데이터를 받을 여유 공간이 없다는 것을 뜻하기 때문이다.
이 윈도우 사이즈가 여유로워질 때까지 송신측은 데이터를 보내지 않고 기다리게 되고 역시나 여기서도 속도 지연이 발생하게 된다.
윈도우 사이즈가 여유가 생기려면 TCP 버퍼에 쌓여있던 데이터들을 소켓 파일 I/O 버퍼 메모리에 올려야 하는데, 이 속도가 네트워크에서 데이터를 수신하는 속도보다 빨라야 송신측이 기다리는 시간이 짧아진다.
네트워크의 지연을 파악하려면 가장 먼저 프로그램의 TCP 버퍼에서 File I/O 버퍼로 올라가는 속도를 파악해야 한다.