hmk run dev

TCP/IP 송수신 원리 (feat. nullnull) 본문

network

TCP/IP 송수신 원리 (feat. nullnull)

hmk run dev 2024. 2. 24. 13:02

 

client와 server가 통신을 한다고 가정해보자
그리고 client가 server에 file하나를 요청한 상황

 


Server


소켓과 서버

 

서버에서 어떤 프로그램이 작동을 하고 있다.

서버에는 socket이 하나 열려있는 상태 그리고 해당 socket으로 통신을 할 예정

 

소켓의 본질은 파일

서버는 프로세스

 

 

프로세스가 파일에 할 수 있는 오퍼레이션은 기본적으로 RWX(Read, Write, Execute)

읽는다, 쓴다라는 개념은 소켓통신인 경우에 조금 다른 개념을 뜻한다.

 

읽는다는, Receive

쓴다는, Send

 

즉, 서버 프로세스가 소켓에다 대고 I/O를 한다고 할 수 있다.


파일 처리

 

기본적으로 서버는 HDD에 파일을 저장하고 있을 것이다.

그리고 파일은 파일 시스템에 의해 관리되고 있을 것인데

 

서버를 JAVA로 개발하든 Node로 개발하든 C++로 개발하든,

서버프로세스엔 메모리가 할당되어 있다.

 

클라이언트가 요청한 파일의 크기가 대략 1.4Mb라고 가정해보자,

보통 서버에 메모리는 개발자가 결정한다.

 

중요한 것은 대부분 1.4Mb 보다 작은 경우가 많다.

64kb 정도로 잡았다고 가정해보자,

 

그래서 File을 읽어 올때 한번에 파일 데이터를 한번에 가져오지 못한다.

64kb만큼 가져와서 메모리에 적재를 한다.

 

 

64kb씩 끊어서 가져온다(Read)

 


 

소켓과 TCP & Buffer

 

소켓이라는 것은 기본적으로 TCP/IP를 추상화 한 것

위에서 가져온 파일데이터를 

 

소켓과 TCP가 맞닿은 지점(TCP소켓)에서 분해가 일어난다.

 

TCP에는 Buffer가 있다(메모리라고 표현하기도 한다.)

 

 

1. HDD에서 가져온 파일 데이터 일부가 TCP 버퍼에 copy된다. (Bufferd I/O)

 

2. TCP의 버퍼가 IP쪽으로 내려가면 데이터는 세그먼트로 분리가 된다. (세그먼테이션)

 

1.4Mb의 파일을 64Kb씩 끊어서 가져온다.

퍼즐을 예로 들어보자, 1.4mb의 크기의 퍼즐을 64kb의 조각으로 채운다.

 

3. IP의 세그먼테이션된 데이터 조각들은 각각 번호가 부여된다. (패킷화)

 

패킷을 택배라고 생각해보자, 택배 상자에는 주소가 적혀져 있고 세그먼트를 배송한다.

 

4. 패킷 하다가 저 너머의 PC쪽으로 날아간다. 인캡슐레이션 (buffer => frame)

 

택배는 택배트럭에 실어서 목적지로 배송된다. (이때 택배는 프레임이라고도 부른다 /L2 수준 네트워크 NIC)

더보기

"네트워크 닉(Network Nickname)"이라는 용어는 일반적으로 네트워크 상에서 사용자가 식별되는 데에 사용되는 별명이나 사용자 이름을 가리킬 때 사용될 수 있습니다. 사용자들은 복잡한 IP 주소 대신에 간편하게 기억 가능한 이름을 사용하여 서로를 식별할 수 있습니다.

트럭의 목적지는 클라이언트고, 택배는 중간에 택배트럭이 바뀔 수도 있다. 그러나, 목적지는 똑같다.

 


Client

 

5. 택배는 클라이언트 프로세스에 도착한다. 

그리고, 서버와 마찬가지로 소켓으로 I/O

그리고 마찬가지로 소켓에 연결된 Buffer를 가지고 있다.

 

 

6. 트럭에서 전달될 택배를 꺼낸다. 디캡슐레이션(frame => Buffer)

 

택배상자에서 세그먼트를 꺼낸다.

세그먼트가 대략 2개 정도 도착하면

TCP는 조립을 한다. (퍼즐 조각을 조립함)

어떤 퍼즐 조각을 받았는지 정보 등을 담아서 잘 수신했다를 서버에게 알려준다. (ACK, feat. Three way handshake)

 

 

서버는 ACK가 올때까지 wait한다.

왜냐하면 순서를 보장해야하기 때문에

(UDP에 비해 TCP가 속도가 느린 큰 이유 중 하나)

 

 

TCP버퍼의 크기는 window size라고 한다.

window size는 수신측에서 세그먼트가 날아오면 조립해서 넣을 수 있는 공간

 

 

ACK를 보낼때, 패킷에 이 window size를 포함하고 있다.

 

 

1. 1,2 번을 잘 받았다는 ACK를 서버측으로 보낸다.

2. 서버는 3번을 전송을 해줘야한다.

    - 여기서 수신측의 window사이즈에 여유 공간이 있는 지를 보고 3번을 보낼지 말지도 결정을 한다.

    - 근데 만약, window size에 여유가 없다? => wait가 발생한다.

 

 

결국, 주로 느리다고 얘기하는게 client 인데 server의 문제가 아닐수도 있다.

 

운영체제는 TCP 버퍼에서 window size에 메모리를 쌓아 놓고,

클라이언트 프로세스의 File I/O Buffer에 빨리 옮겨야 하는데,

 

이 속도(Read 속도)가 네트워크에서 수신하는 속도보다 무조건 빨라야한다.

 

그렇지 않다면 window size의 여유가 점점 더 사라진다.

물론 다른 이유도 있겠지만

통신 속도가 느리다면, window size를 잘 체크하자

 

노파심에 말하자면, window size가 무조건 크다고 좋은게 아니다...!

상황에 맞게 설정이 필요하다 우리는 소프트웨어 개발자니까... 

 

 


참고로 mac에서 tcp window size를 확인하려면

 

"sysctl net.inet.tcp" 명령어로 확인할 수 있다.

 

net.inet.tcp.sendspace: 131072

net.inet.tcp.recvspace: 131072

 

 

 

기본적으로 바이트 단위로 표기된다.

 

1. 킬로바이트(KB) = 1024 바이트

따라서, 131072 바이트를 킬로바이트로 변환하면 다음과 같음
131072 바이트 ÷ 1024 = 128 KB

따라서 제 컴퓨터의 window size인 131072 byte = > 128 kb

 

 


 

Reference

 

https://www.youtube.com/watch?v=K9L9YZhEjC0&t=697s

'network' 카테고리의 다른 글

TCP/IP? OSI 7계층?  (0) 2024.03.04
HTTP와 HTTPS  (0) 2024.03.03
Comments