네트워크 원리 chapter 2 - 4
4. 서버에서 연결을 끊어 소켓을 말소한다.
1. 데이터 보내기를 완료하고 연결을 끊는다
-
소켓 연결 말소 시점은 한쪽이 데이터 보내기를 완료했을때다.
- 어느 측에서든 먼저 연결을 끊을 수 있도록 프로토콜이 설계 되어 있다.
- 주로 브라우저에서 요청을 보내고 서버에서 응답을 하면 서버 측에서 먼저 연결 끊기 동작을 실행한다.
- 주로 브라우저에서 요청을 보내고 서버에서 응답을 하면 서버 측에서 먼저 연결 끊기 동작을 실행한다.
-
close 메소드를 호출해서 연결끊기 동작에 들어간다.
- 연결끊기 동작 세부 로직 - 끊는 쪽 (예. 서버)
- 연결을 끊고자 하는 측이 TCP 헤더를 만들어서 FIN 컨트롤 비트를 1로 설정한다.
- 이 패킷을 IP 담당에게 요청하여 상대에게 송신한다.
- 자신의 소켓에 연결 끊기 동작에 들어갔다는 사실을 통지한다.
- 연결끊기 동작 세부 로직 - 상대 쪽 (예. 브라우저)
- 프로토콜 스택이 소켓에 연결 끊기 동작이 들어갔다는 것을 기록하고 패킷을 잘 받았다는 뜻으로 ACK를 보낸다.
- 어플리케이션이 read를 할 때 데이터를 건내는 대신 데이터 수신을 완료했음을 알리고 FIN을 1로 한 헤더를 IP 담당에게 넘겨 반송한다.
- 서버에서 ACK를 보내면 연결이 끊기가 완료된다.
2. 소켓을 말소한다
- 연결 끊기 동식이 실행되었을 때 소켓을 곧바로 말소하지 않고 기다린 후에 소켓을 말소한다.
- 이유는 ACK가 서버에 도착하지 않아서 서버가 다시 FIN을 전송하게 되는 경우 담당 소켓이 말소되었으므로 동일한 포트번호의 새로운 소켓을 생성하게 되고 해당 소켓에 FIN이 도착하여 오동작하게 된다.
3. ACK 번호를 사용하여 패킷이 도착했는지 확인한다
-
TCP에는 송신한 패킷이 상대에게 올바르게 도착했는지 확인하고, 도착하지 않았으면 다시 송신하는 기능이 있으므로 패킷을 송신한 후에는 확인 동작으로 넘어간다.
-
데이터를 조각으로 분할할 때 조각이 통신 개시부터 따져서 몇 번째 바이트에 해당하는지를 세어둔다. 그리고 데이터의 조각을 송신할 때 세어둔 값을 TCP 헤더에 기록하는데, 시퀀스 번호라는 항목이 해당된다. 패킷 전체의 길이에서 헤더 길이를 빼면 데이터의 크기를 계산할 수 있으므로 수신측에서 이 방법에 따라 크기를 산출한다.
-
누락이 없는 것을 확인하면 수신측은 그 이전에 수신한 데이터와 합쳐서 데이터를 몇 번째 바이트까지 수신한 것인지 계산하고, 그 값을 TCP 헤더의 ACK 번호에 기록하여 송신측에 알려준다. 이렇게 ACK 번호를 되돌려주는 동작을 수신 확인 응답이라고 부른다.
-
실제로 시퀀스 번호는 1부터 시작하지 않고 난수를 바탕으로 산출한 초기값으로 시작한다. 데이터의 송/수신을 시작하기 전에 초기값을 상대에게 알리게 되어 있다.
-
TCP는 상대가 데이터를 받았는 지 확인할 때까지 송신한 패킷을 송신용 버퍼 메모리 영역에 보관해둔다. 그리고 대응하는 ACK 번호가 상대로부터 돌아오지 않으면 패킷을 다시 보낸다. 이렇기 때문에 다른 곳에서 오류를 회복 조치할 필요가 없다.
-
TCP는 몇 번 다시 보낸 후 회복의 전망이 없는 것으로 보고 데이터 송신 동작을 강제로 종료하고 애플리케이션에 오류를 통지한다.
4. 패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다
-
ACK 번호가 돌아오는 것을 기다리는 시간을 타임아웃 값이라고 한다. 대기 시간은 너무 짧지도, 길지도 않은 적절한 값으로 설정해야 한다. 하지만 이것은 어려운 것이다. 그래서 TCP는 대기 시간을 동적으로 변경하는 방법을 취하고 있다. ACK 번호가 돌아오는 시간을 기준으로 대기 시간을 판단하는 것이다.
-
데이터 송신 동작을 실행하고 있을 때 항상 ACK 번호가 돌아오는 시간을 계측해둔다. 그리고 ACK 번호가 돌아오는 시간이 지연되면 이것에 대응하여 대기 시간도 늘린다. 반대로 ACK 번호가 곧바로 돌아오면 대기 시간을 짧게 설정한다.
5. 윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다
-
ACK 번호가 돌아올 때까지 아무 일도 하지 않고 기다리는 것은 시간 낭비이다.
-
윈도우 제어는 한 개의 패킷을 보낸 후 ACK 번호를 기다리지 않고 차례대로 연속해서 복수의 패킷을 보내는 방법이다.
-
그러나 ACK 번호를 기다리지 않고 차례로 패킷을 보내면 수신측의 능력을 초과하여 패킷을 보내는 사태가 일어날 수도 있다.
-
수신측의 TCP는 패킷을 수신하면 일단 수신용 버퍼 메모리에 데이터를 일시 보관한다. 수신측에서는 ACK 번호를 계산하거나 조각을 연결하여 원래 데이터를 복원한 후 애플리케이션에 건네주어야 한다. 그런데 애플리케이션에 건네주는 속도보다 빠른 속도로 데이터가 도착하면 수신 버퍼에 데이터가 차곡차곡 쌓여서 곧 넘쳐버린다.
-
이 문제는 수신측에서 송신측에 수신 가능한 데이터 양을 통지하고, 송신측은 이 양을 초과하지 않도록 송신 동작을 실행하는데, 이것이 윈도우 제어 방식의 개념이다.
-
TCP 헤더의 윈도우 필드에서 이것을 알려준다. 수신 가능한 데이터 양의 최대값을 윈도우 사이즈라고 부르고, 보통 수신측의 버퍼 메모리의 크기와 같은 크기가 된다.
6. ACK 번호와 윈도우를 합승한다
-
윈도우 통지가 필요한 것은 수신측이 수신 버퍼에서 데이터를 추출하여 애플리케이션에 건네주었을 때이다. 수신측에서 애플리케이션에 데이터를 건네주고 수신 버퍼의 빈 영역이 늘어났을 때, 이것을 송신 측에 통지해야 하는데 이것이 윈도우 통지의 타이밍이다.
-
ACK 번호는 데이터를 수신한 후 즉시 보낸다고 볼 수 있다.
-
설명대로라면 ACK 번호 통지와 윈도우 통지의 패킷이 하나씩 따로따로 송신측에 보내지는 데, 이것은 효율성이 저하된다.
-
수신측은 ACK 번호나 윈도우를 통지할 때 소켓을 바로 보내지 않고 잠시 기다렸다가 다음 통지 동작이 일어나면 한 개의 패킷으로 묶어서 보낸다.
-
복수의 ACK 번호 통지가 연속해서 일어나는 경우도 최후의 것만 통지하고 도중의 것은 생략해도 상관 없다.
7. HTTP 응답 메시지를 수신한다
- 브라우저는 요청 메시지를 송신해 달라고 의뢰하고, 서버에서 돌아오는 응답 메시지를 받기 위해 read 프로그램을 호출한다. read를 경우하여 프로토콜 스택에 제어가 넘어가고, 프로토콜 스택이 움직이기 시작한다.
Leave a comment