프로토콜 스택에 HTTP 리퀘스트 메시지를 넘긴다송신용 버퍼 메모리에 어느정도까지 저장할지 판단할 때 고려 요소1. MTU, MSS2. 타이밍정리데이터가 클 때(MSS 보다 데이터가 클 때)는 분할하여 보냄ACK 번호를 사용하여 패킷이 도착했는지 확인함개념실제 움직임패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다윈도우 제어와 수신용 메모리 ACK 번호와 윈도우를 합승한다HTTP 응답 메시지를 수신한다
프로토콜 스택에 HTTP 리퀘스트 메시지를 넘긴다
- connect에서 애플리케이션에 제어가 되돌아오면 데이터 송.수신 동작에 들어감. 이 동작은 애플리케이션이 write를 호출하여 송신 데이터를 프로토콜 스택에 건네주는 곳부터 시작
- 프로토콜 스택은 받은 데이터를 곧바로 송신하는 것이 아니라 일단 자체의 내부에 있는 송신용 버퍼 메모리 영역에 저장하고 애플리케이션이 다음 데이터를 건네주기를 기다림
- 송신을 의뢰할 때 애플리케이션에서 프로토콜 스택에 건네주는 데이터의 길이는 애플리케이션의 종류나 만드는 방법에 따라 결정됨. 데이터를 전부 한꺼번에 송신 의뢰하는 경우도 있고, 1바이트씩 또는 1행씩 세분하여 송신 의뢰하는 경우도 있음 ( 즉, 데이터의 길이가 어플리케이션의 사정에 따라 결정됨. 프로토콜 스택에서 제어 x )
- 받은 데이터를 그대로 보내는 단순한 방법에서는 작은 패킷을 많이 보냄으로, 네트워크의 이용 효율이 저하됨
송신용 버퍼 메모리에 어느정도까지 저장할지 판단할 때 고려 요소
1. MTU, MSS
- MTU : 한 패킷으로 운반할 수 있는 디지털 데이터의 최대 길이. 이더넷에서는 보통 1,500 바이트가 됨
- MSS : MTU에는 패킷의 맨 앞 부분에 헤더가 포함되어 있으므로 헤더를 제외한 데이터의 최대길이
- 애플리케이션에서 받은 데이터가 MSS를 초과하거나 MSS에 가까운 길이에 이르기까지 데이터를 저장하고 송신 동작을 하면 패킷이 잘게 나누어질 걱정 할 필요 없음
2. 타이밍
- 애플리케이션의 송신 속도가 느려지는 경우 MSS에 가깝게 데이터를 저장하면 여기에서 시간이 걸려 송신 동작이 지연됨 ⇒ 프로토콜 스택은 내부에 타이머가 있어서 이것으로 일정 시간 이상 경과하면 패킷 송신함
정리
- 전자를 중시하면 패킷 길이가 길어져서 네트워크의 이용 효율이 높아지지만 버퍼에 머무는 시간만큼 송신 동작이 지연될 우려가 있음
- 후자를 중시하면 지연은 적어지지만 이용 효율이 떨어지므로 양자를 절충해서 적당히 시간을 가늠하여 송신 동작 실행해야 함
- 실제로 어떻게 판단해야 할 지는 프로토콜 스택을 만드는 개발자에게 맡겨져 있음
- 애플리케이션 측에서 송신의 타이밍을 제어할 수도 있음
- 데이터 송신 의뢰 시, 옵션 지정할 수 있으며, ‘버퍼에 머물지 않고 바로 송신할 것'이라고 지정하면 프로토콜 스택은 버퍼에 머물지 않고 송신동작 실행함
데이터가 클 때(MSS 보다 데이터가 클 때)는 분할하여 보냄

- 블로그나 게시판 등에서 긴 문장 투고할 경우 데이터가 매우 크므로 송신 버퍼에 데이터 저장 후 다음 데이터 기다릴 필요가 없음
- TCP 가 데이터를 조각내서 TCP 헤더 부가후, 소켓에 기록되어 있는 제어 정보를 바탕으로 송신처 포트 번호, 수신처 포트 번호 등 중요 항목 기록하고 IP 담당 부분에 건네주어 송신 동작 실행함
ACK 번호를 사용하여 패킷이 도착했는지 확인함
개념

- TCP 담당 부분은 데이터를 조각으로 분할할 때 조각이 통신 개시부터 따져서 몇 번째 바이트에 해당 하는지를 세어둠
- 그리고 데이터의 조각을 송신할 때 세어둔 값을 TCP 헤더에 기록하는데, 시퀀스 번호라는 항목이 이에 해당됨
- 데이터의 크기는 패킷 전체의 길이에서 헤더 길이를 빼면 계산 가능하므로 전달 따로 안함
- 1,460번째 바이트까지 수신 완료한 상태에서 시퀀스 번호가 1,461인 패킷이 도착하면 누락이 없다는 것을 알 수 있고, 시퀀스 번호가 1461인 패킷이 도착하지 않았는데 시퀀스 번호가 2921인 패킷이 도착하면 누락된 것을 알 수 있음
- 이렇게 해서 누락이 없는 것을 확인하면 수신측은 그 이전에 수신한 데이터와 합쳐서 데이터를 몇 번째 바이트까지 수신한 것인지 계산하고 그 값을 TCP 헤더의 ACK 번호에 기록하여 송신측에 알려줌 ( 수신 확인 응답 ) → 송신측은 이것을 통해 상대가 어디까지 수신했는지를 파악함
- 즉 송신측은 ACK 응답을 통해 어디까지 수신했는지 파악
- 수신측은 시퀀스 번호와 데이터 크기를 통해 어디까지 받았는지 파악 & 다음 시퀀스 번호가 받은 내용의 바로 다음인지를 보고 누락여부 파악 가능. 누락되지 않았다면 데이터 이어 붙임
- 해당 예에서는 시퀀스 번호가 1부터 시작하지만 실제로는 난수를 바탕으로 산출한 초기값으로 시작함. (항상 1로 시작하면 악의적 공격의 우려가 있기에)
- 그래서 송.수신 시작 전에 초기값을 상대에게 알려야 함(SYN 제어 비트를 1로 하여 서버에 보낼 때, 시퀀스 번호에 값을 설정해서 알려줌)
실제 움직임

- 클라이언트에서 서버로 보내는 데이터에 관한 시퀀스 번호의 초기값을 클라이언트에서 산출하여 서버에 통지
- 서버에서 초기값으로 부터 ACK 번호 산출하여 클라이언트에 반송. 서버에서 클라이언트에 보내는 데이터에 관한 시퀀스 번호 초기값 산출하여 클라이언트에 통지
- 클라이언트에서 서버로부터 받은 시퀀스 번호 초기값으로부터 ACK 번호 산출하여 서버에 반송
- 웹의 경우 최초에 클라이언트에서 서버로 메시지를 보낼 것이고, 데이터와 함께 시퀀스 번호를 보냄
- 데이터를 수신한 서버에서 ACK 번호를 반송
- 7 : 서버에서 클라이언트에 데이터를 보내는 경우에는 그 반대
TCP는 이 방법으로 상대가 데이터를 받은 것을 확인하는데, 확인할 때까지 송신한 패킷을 송신용 버퍼 메모리 영역에 보관해 둠. 그리고 송신한 데이터에 대응하는 ACK 번호가 상대로부터 돌아오지 않으면 패킷을 다시 보냄 → 이 구조는 매우 강력하여 회복 처리를 다른 곳에서 할 필요가 없음 ( 다른 곳에서는 오류 검출 시 그 패킷 버림)
단, 케이블 분리되거나 서버가 다운되는 등의 이유로 TCP가 아무리 다시 보내도 데이터가 도착하지 않으면 송신 동작 강제종료하고 어플리케이션에 오류 통지함
패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다
- ACK 번호가 돌아오는 것을 기다리는 시간 — 타임아웃 값
- 네트워크가 혼잡하여 정체가 일어나면 ACK 번호가 돌아오는 것이 지연되므로 이것을 예측하여 대기 시간을 어느 정도 길게 설정해야 함
- 소모적인 다시 보내기는 단순히 낭비가 아닌, ACK 반송이 지연되도록 한 사태가 혼잡이 원인인 경우가 많으므로 거기에 패킷을 보내면 혼잡을 악화시키기도 함
- 대기 시간이 너무 짧으면 혼잡 악화, 대기시간이 너무 길면 패킷을 다시 보내는 동작이 지연되어 속도 저하의 원인이 됨
- 서버가 가까운지, 먼지에 따라 ACK 번호가 돌아오는 차이도 크고, 정체시의 지연도 가미하여 생각해야 하기 때문에 대기 시간 설정이 쉽지 않음
- 그래서 TCP 는 대기 시간을 동적으로 변경하는 방법을 취함. ACK 번호가 돌아오는 시간을 기준으로 대기 시간 판단
- 구체적으로, 데이터 송신 동작 실행하고 있을 때 항상 ACK 번호가 돌아오는 시간을 계측해 둠
- ACK 번호 돌아오는 시간이 지연되면 이것에 대응하여 대기 시간도 늘림
- ACK 번호가 곧바로 돌아오면 대기 시간을 짧게 설정
윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다

- 한 개의 패킷을 보내고 ACK 번호를 기다린다는 방법(핑퐁 방식)은 단순하고 이해하기 쉽지만, ACK 번호가 돌아올 때까지의 시간 동안 아무 일도 하지 않고 기다리는 것은 시간 낭비임
- → 윈도우 제어라는 방식에 따라 송신과 ACK 번호 통지의 동작을 실행
- 주의점 : ACK 번호를 받기 전에 보내버리면 수신측의 능력을 초과하여 패킷을 보내버릴 수 있음
- 수신측에서는 ACK 번호를 계산하거나 조각을 연결하여 원래 데이터를 복원한 후 애플리케이션에 건네주어야 하므로 수신 버퍼에 수신된 데이터 일시 저장함
- 그런데 어플리케이션에 건네주는 속도보다 빠른 속도로 데이터가 도착하면 수신 버퍼에 데이터가 차곡차곡 쌓여서 곧 넘쳐버리게 됨
윈도우 제어와 수신용 메모리
윈도우 사이즈 ( 보통 수신측 버퍼 메모리의 크기와 같은 크기 )
- 수신측은 수신용 버퍼에 데이터를 임시 보관하고 수신처리를 진행하는데,
- 수신 처리가 끝나고 수신 버퍼에 빈 부분이 생기면 그 분량만큼 수신할 수 있는 데이터 양을 늘리므로 TCP 헤더의 윈도우 필드에서 이것을 송신측에 알림
- 송신측에서는 해당 윈도우 필드 헤더를 확인하고 데이터를 그 사이즈를 고려하면서 보내게 됨. 빈 영역이 0이 되게 되면 송신을 중지함
- 수신측 프로그램에서 애플리케이션이 데이터를 가져가게 되면 수신 버퍼가 비워지게 되고 빈 영역이 업데이트 되면 해당 빈 영역의 사이즈를 송신측에 다시 보내줌
ACK 번호와 윈도우를 합승한다
- 송.수신 동작의 효율성을 높이기 위해 ACK 번호와 윈도우를 통지하는 타이밍을 고려해야 함
- 두 가지를 별개의 것으로 생각하고 각각 별도의 패킷으로 보내면 비효율적
- 윈도우 통지 타이밍 : 수신 버퍼에서 데이터를 추출하여 애플리케이션에 건네주었을 때
- ACK 번호 통지 타이밍 : 수신측에서 데이터를 받았을 때 내용 조사 후 정상 수신을 확인할 수 있는 경우에 송신측에 보냄
- 수신측은 ACK 번호나 윈도우를 통지할 때 소켓을 바로 보내지 않고 잠시 기다렸다가, 다음 통지 동작 일어나면 두 정보를 한 개의 패킷으로 묶어서 보냄
- 예를 들어 ACK 번호 송신 대조시, 윈도우 통지 일어나면 합승시켜서 통지
- 복수의 ACK 번호 통지가 연속해서 일어난 경우에도 최후 것만 통지하고 도중의 것은 생략해도 됨
HTTP 응답 메시지를 수신한다
- 수신한 데이터 조각과 TCP 헤더의 내용을 조사하여 도중에 데이터가 누락되었는지 검사하고, 문제가 없으면 ACK 번호를 반송함
- 그리고 데이터 조각을 수신 버퍼에 일시 보관하고, 조각을 연결하여 데이터를 원래 모습으로 복원한 후 애플리케이션에 건네줌
- 구체적으로는 수신 데이터를 애플리케이션이 지정한 메모리 영역에 옮겨 기록한 후 애플리케이션에 제어를 되돌려 줌