본 내용은 “성공과 실패를 결정하는 1%의 네트워크” 를 참고하여 작성하였습니다.
connect를 통해서 데이터 송수신이 준비가 완료되면, 어플리케이션은 Soket라이브러리에서 write를 호출하여 송신데이터를 프로토콜 스택에 넘겨준다.
이때 데이터를 송신하는 기준은 크게 몇가지가 있다
- 데이터의 크기
- 타이밍
데이터의 크기
중요한점
- 프로토콜 스택에 넘어간 데이터를 프로토콜 스택은 인식하지못한다. 바이너리 값으로 인식함
- 버퍼 메모리 영역에 저장함 → 이는 어플리케이션 마다 프로토콜스택에 데이터를 넘겨주는 방법이 다르기 때문이다.
- 또한 바로바로 패킷단위의 데이터를 보내면 효율이 떨어질수도 있기 때문에 이를 잘 고려해서 보내게 된다.
- 어느정도의 데이터 양을 기준으로 하는지에 대해서는 MTU를 바탕으로 계산하게 된다.
- MUT란, 한 패킷으로 운반할수있는 데이터의 최대 길이이며 보통 1500바이트가 된다.
- MSS란, MTU에서 헤더를 제외한 것으로, 정확히 패킷으로 전달할수 잇는 ‘데이터’의 길이가 된다.
타이밍
타이밍이란 어플리케이션의 송신 속도가 느린 경우에는 MSS에 가깝게 데이터를 저장하면 여기에서 시간이 결러 송신 동작이 지연된다. (데이터가 크면 MSS가 커지고 MSS에 저장하는 시간이 지연되기 때문)
이럴때는 그냥 버퍼에 저장하지 않고 송신하게 되며
이러한 시간을 프로토콜 스택 내부의 타이머로 측정한다.
일정수준이 되면 데이터를 송신해버린다.
데이터의 분할
http 메세지는 하나의 패킷에 들어가지만, 폼을 통해서 대량의 데이터를 보내게 되면 어떻게 될까?
송신버퍼에 저장된 데이터가 MSS의 길이를 초과 하기 때문에 버퍼의 데이터를 MSS패킷 크기에 맞게 분할하여 순서대로 송신한다.
ACK번호
이전에도 이야기 했지만, TCP 프로토콜에는 송신한 패킷이 제대로 도착했는지 확인하고, 에러가 났다면 다시 보내는 동작을 하게 된다. 따라서 송신후, 확인동작을 실행한다.
데이터의 사이즈가 크면 우리는 여러개의 패킷으로 나눠서 송신하게 되는데
몇개의 데이터 조각으로 나눈지에 대한 시퀸스 번호를 TCP헤더에 저장하고 송신하게 된다.
수신측에서는 총 데이터의 길이만을 알게 되는데, 이는 패킷에서 헤더를 제외한 데이터 길이를 통해서 몇개의 패킷이 올지를 계산할수 있기 때문이다.
수신측에서는 이렇게 시퀸스 번호를 통해서 몇번째 패킷까지 수령했는지에 대해서 몇번째 데이터 까지 수신한것인지 TCP헤더에 포함해서 다시 송신측에 보내준다.
즉, 2233 번째가 도착햇는데 2239가 도착하면 그 사이에 값이 없어졌다는것을 알수 있게 되는것이다.
ACK번호를 되돌려주는것을 수신확인 응답 이라고 한다.
즉 ACK번호를 되돌려 주는것으로 지금 몇번쨰~ 데이터까지 왔어~ 라고 알려주는 것이다.
SYN에서 시퀸스 초기값
데이터 시퀸스의 초기값이 항상 1이라면 악의적인 공격에 대해서 방어하지 못하기 때문에,
난수를 생성하고 그 값부터 데이터 시퀸스를 하나씩 준다.
따라서 이 초기값을 서버에 알려줘야 하고, 앞의 접속 동작에서 이를 통지한다.
이 초기값이 시퀀스 번호 초기값이다. 라고 알려주는 것이 SYN이다.
이러한 과정을 통해서 송 수신이 정상적으로 됏다는 것을 서로 알려주게 된다.
- 송신한 패킷의 번호를 버퍼에 저장한다.
- 이에 대응하는 ACK 번호를 리턴받지 않으면 정상적으로 도착하지 않은것이기 때문에
- 다시 해당 번호에 해당하는 데이터를 보낸다.
타임아웃
위의 방식에서 데이터의 오류에 대해서는 전혀 검출하지 않는다는 단점이 존재한다.
데이터만 도착하면 ACK번호를 리턴받기 때문이다.
또한 중간에 서버가 끊기거나 하면 계속해서 데이터를 보내는것도 문제가 된다.
이를 해결하기 위해서 ACK번호가 돌아오는 대기 시간을 지정해두게 된다.
이 대기시간을 타임아웃 값 이라고 한다.
이러한 타임아웃값은 첫번째 받은 ack 값에 따라서 동적으로 설정해준다.
→ 거리에 따라서 시간이 다르기 때문에 동적으로 설정해준다.
윈도우 제어 방식
하나의 패킷을 송신하고 ACK번호를 받을때까지 기다리기만 하면 매우 비효율적이다.
따라서 윈도우 제어라는 방식으로 ACK번호를 기다리지 않고, 복수의 패킷을 보낸다.
이렇게 계속해서 데이터를 보내는것은 송신측에서는 매우 효율적이나, 수신측에서는 부담이 된다.
수신받은 데이터를 처리하지 않았는데 계속해서 데이터가 넘어오게 되고 이를 버퍼에 저장을 하게 되도
버퍼의 용량을 넘어버리게 되면, 넘어오는 패킷내용을 수신처리할수 없게 되기 때문.
따라서 이 양이 넘어가지 않도록 송신측에 알려주는것이 윈도우 제어 방식이다.
윈도우 필드
TCP 헤더에 수신측의 수신 버퍼의 남은 데이터 량을 포함하여 송신측에 보내게 된다.
이때 TCP 헤더에 저장되는 부분이 바로 윈도우 필드이다.
- 윈도우 사이즈 : 수신가능한 데이터 양의 최대값
HTTP 응답 메세지를 수신
이렇게 데이터를 전달 받게 되고 브라우저에 뿌리는 과정은 다음과 같다.
- http 리퀘스트 메세지를 보낸다.
- 응답 메세지를 받기 위해서 프로토콜 스택에서 read를 부르게 된다.
- read를 통해서 수신한 데이터를 수신 버퍼에 저장하게 된다.
- 응답 메세지를 수신한다.
- 버퍼에 저장된 조각 데이터를 연결하여 원래 모습으로 복원한뒤 어플리케이션에 전달한다.
- 어플리케이션은 이를 화면 뿌린다.
- 이후 타이밍을 가늠하여 윈도우필드를 송신측에 통지하게 된다.
Uploaded by N2T