Post

[1% network] Ch06. 웹서버에 도착하여 응답데이터가 웹브라우저로 돌아간다

Ch06. 웹서버에 도착하여 응답데이터가 웹브라우저로 돌아간다

학습할 것

  • 서버의 개요
  • 서버의 수신 동작
  • 웹 서버 소프트웨어가 리퀘스트 메시지의 의미를 해석하여 요구에 응한다
  • 웹 브라우저가 응답 메시지를 받아 화면에 표시한다

서버의 개요

1. 클라이언트와 서버의 차이점

  • 접속 동작 시 클라이언트에서 접속 동작을 수행하고 서버는 그것을 기다리는 형태가 되므로 호출하는 Socket 라이브러리의 프로그램이 다르다.
  • 서버의 애플리케이션은 다수의 클라이언트 PC와 대화한다.

2. 서버 애플리케이션의 구조

서버와 클라이언트가 일대일로 연결되는 방식

  • 서버 OS의 멀티태스크, 멀티스레드 기능을 사용한 기법이다.
  • 서버 프로그램을 클라이언트의 접속을 기다리는 부분클라이언트와 대화하는 부분으로 나누어 만든다.
  • 서버 프로그램의 성정 파일 읽기 등의 초기화 동작을 마쳤을 때 접속을 기다리는 부분을 실행한다.
    • 소켓 작성, 소켓을 클라이언트에서 접속 동작을 기다리는 상태로 만들고 쉬는 상태가 된다.
  • 클라이언트가 접속했을 때 클라이언트와 대화하는 부분을 실행한다.
    • 접속을 접수하면 클라이언트와 대화하는 부분 즉 새 태스크/스레드를 생성하고 접속할 때 새로 생성한 소켓을 건네준다.

3. 서버측의 소켓과 포트 번호

  • 서버와 클라이언트의 역할은 고정되어 있지 않고 여러 형태로 변경되며 데이터를 송수신할 수 있으므로 그에 맞게 좌우대칭으로 실행될 수 있도록 하는 것이 좋다.
  • 그러나 TCP의 접속 동작은 한쪽이 소켓을 열고 기다리며 다른 한쪽을 연결해야하므로 좌우 대칭으로 만들 수 없다.
    • 접속하는 측 (클라이언트)과 접속을 기다리는 측(서버)의 역할 분담이 필요하다.
    • 이는 Socket 라이브러리 호출하는 방식에 차이가 있다.

클라이언트의 데이터 송수신 동작

  • 소켓을 만든다. (소켓 작성 단계)
  • 서버측의 소켓과 파이프로 연결한다. (접속 단계)
  • 데이터를 송수신한다. (송수신 단계)
  • 파이프를 분리하고 소켓을 말소한다. (연결 끊기 단계)

서버의 데이터 송수신 동작

  • 소켓을 만든다. (소켓 작성 단계)
    • socket을 호출한다.
  • 소켓을 접속 대기 상태로 만든다. (접속 대기 상태)
    • bind를 호출하여 소켓에 서버 어플리케이션의 포트 번호를 기록한다.
    • listen을 호출하여 소켓에 접속하기를 기다리는 상태라는 제어 정보를 기록한다.
  • 접속을 접수한다. (접속 접수 단계)
    • 클라이언트의 접속 패킷이 도착하기 전 accept를 호출하여 접속을 접수한다.
    • accept를 실행한 이후 패킷의 도착을 기다리는 상태가 되고 애플리케이션에서 접속 패킷이 도착하면 응답 패킷을 반송하여 접속 접수 동작을 실행한다.
    • 접속 대기 소켓을 복사하여 새로운 소켓을 만들고 접속 상대의 정보를 비롯한 제어 정보를 새 소켓에 기록한다.
  • 데이터를 송수신한다. (송수신 단계)
  • 파이프를 분리하고 소켓을 말소한다. (연결 끊기 단계)

서버의 접속 동작 시 새 소켓을 만드는 이유

  • 새 소켓을 만들지 않고 접속 대기의 소켓에 그대로 접속하면 접속 대기의 소켓이 없어져 버리므로 다음에 다른 클라이언트가 접속할 경우 문제가 생기기 때문이다.
  • 그래서 복사한 소켓은 원래 소켓과 같은 포트번호를 부여받고 원래 소켓은 남아서 접속을 받는다.

소켓 지정 시 식별하기 위해 필요한 정보

  • 클라이언트 IP주소
  • 클라이언트 포트 번호
  • 서버 IP주소
  • 서버 포트 번호

위의 4가지 정보로도 소켓을 식별할 수 있지만 디스크립터가 필요한 이유는 뭘까?

디스크립터가 필요한 이유

  • 접속을 대기할 때는 아직 클라이언트 소켓이 지정되지 않았으므로 정보가 없다.
  • 디스크립터 하나로 소켓을 식별하는 것이 더 간단하다.

서버의 수신 동작

1. LAN 어댑터에서 수신 신호를 디지털 데이터로 변환한다

  • LAN 어댑터는 전기나 빛의 형태로 도착한 패킷의 신호를 디지털 데이터로 바꾼다.
  • LAN에 흐르는 패킷의 신호는 1과 0으로 이루어진 디지털 데이터의 신호와 타이밍을 나타내는 클록 신호를 합성한 것이다. 여기서 클록 신호를 추출하고 클록 신호에서 타이밍을 계산하여 신호를 읽어 디지털 데이터로 변환한다.
  • 프레임 체크 시퀀스(FCS)라는 오류 검사용 데이터를 이용하여 오류 유무를 검사한다.
  • MAC 헤더에 있는 수신처 MAC 주소를 조사하여 수신처가 본인인지 확인한다.
    • 이더넷은 LAN 전체에 신호를 흘리고 상대를 찾는 형태이기 때문에 올바른 패킷이 아니더라도 도착할 수 있기 때문이다.
  • 변환된 디지털 데이터를 LAN 어댑터 내부의 버퍼 메모리에 저장한다. (여기까지 LAN의 MAC 부분이 담당한다)
  • LAN 어댑터에서 CPU에게 인터럽트로 패킷이 도착했다는 사실을 알린다.
  • LAN 드라이버는 LAN 어댑터의 버퍼 메모리에서 수신한 패킷을 추출하여 MAC 헤더로부터 프로토콜을 판별하고 적합한 프로토콜 처리 소프트웨어를 호출하여 프로토콜 스택에 패킷을 건넨다.

2. IP 담당 부분의 수신 동작

  • 프로토콜 스택에 패킷이 전달되면 IP 담당 부분이 IP 헤더를 점검하고 수신처가 본인 IP인지 확인한다.
    • 서버가 라우터와 같이 패킷을 중개하는 역할일 수 있으므로 본인에게 온 패킷이 아닐수도 있다. 이 경우에는 패킷에 쓰인 수신처 IP 주소로 패킷을 중개해야한다.
  • IP 담당에서는 fragmentation에 의해 패킷이 분할되었는지 조사하고 그렇다면 패킷을 일시적으로 메모리에 저장하고 패킷이 모두 모이면 복원한다.
  • IP 헤더의 프로토콜 번호를 조사하여 해당 부분에 패킷을 건내준다.
    • 06이면 TCP 담당, 11이면 UDP 담당

TCP 담당 부분의 동작은 패킷의 내용에 따라 달라진다.

3. TCP 담당 부분이 접속 패킷을 수신했을 때의 동작

  • 도착한 패킷의 SYN 비트가 1이라면 접속 동작의 패킷이다.
  • 수신처 포트 번호를 조사하여 해당 포트 번호와 일치하는 접속 대기 소켓이 있는지 확인한다.
    • 만일 없다면 오류이므로 오류 패킷을 클라이언트에게 반환한다.
  • 접속 대기 소켓을 찾으면 소켓을 복사하여 새로운 소켓을 만들고 송신처IP주소, 포트번호, 시퀀스 초기값, 윈도우 값등 필수 정보를 기록한다.
  • 동시에 송신 버퍼나 수신 버퍼로 사용하는 메모리 영역을 확보한다.
  • 패킷을 받았다는 ACK 번호, 서버의 시퀀스 초기값, 수신 버퍼 빈 용량인 윈도우 값 등을 기록한 TCP 헤더를 만들고 IP 담당에 의뢰하여 반송한다.
  • 패킷이 잘 도착하면 클라이언트에서 패킷을 받았음을 나타내는 ACK 번호가 돌아와 접속 동작이 완료된다.

4. TCP 담당 부분이 데이터 패킷을 수신했을 때의 동작

  • TCP 담당 부분은 도착한 패킷이 어느 소켓에 해당하는지 조사한다.
    • 서버측에 같은 포트 번호를 가진 소켓이 많으므로 앞에서 언급한 소켓 지정 시 식별하기 위해 필요한 4가지 정보를 통해 소켓을 찾는다.
  • 해당 소켓을 발견하면 소켓에 기록된 정보들을 통해 올바르게 데이터 송수신이 이루어지고 있는지 확인한다.
    • 시퀀스 번호, 지난 데이터 조각의 길이로부터 다음 시퀀스 번호 값 계산, 도착한 패킷의 TCP 헤더에 기록된 시퀀스 번호와 일치하는지
  • 패킷에서 추출된 데이터를 수신 버퍼에 저장한다.
  • 데이터를 수신하면 수신 응답용 TCP 헤더를 만들고 수신 패킷에 시퀀스 번호와 데이터 길이로 얻은 ACK 번호를 기록하고 IP 담당에 넘겨 클라이언트에게 반송한다.
  • 수신 버퍼에 기록된 데이터들은 Socket 라이브러리의 read를 호출하여 어플리케이션에 넘겨진다.
  • 어플리케이션에서 http 리퀘스트 메시지 내용을 조사하고 브라우저에서 데이터를 반송한다

5. TCP 담당 부분의 연결 끊기 동작

  • 어느 쪽(클라이언트 or 서버) 에서든 연결 끊기 동작에 들어가도 상관없다.
    • HTTP 1.0 이라면 서버에서 연결 끊기 동작을 시작한다.
  • 서버에서 close를 호출하고 FIN 1로 설정한 TCP 헤더를 클라이언트에게 보낸다.
  • 클라이언트도 close 를 호출하고 FIN 1로 설정하여 반송하고 ACK도 보낸다.
  • 잠시 기다렸다가 소켓을 말소한다.

웹 서버 소프트웨어가 리퀘스트 메시지의 의미를 해석하여 요구에 응한다

  • 웹서버의 경우 read를 호출하여 받은 데이터의 내용이 HTTP 리퀘스트 메시지가 된다.
  • 리퀘스트 메시지에 기록된 내용에 따라 적절한 처리를 실행하여 응답 메시지를 만든다.
  • write를 통해 이 메시지를 클라이언트에 반송하는 동작을 실행한다.

1. 조회의 URI를 실제 파일명으로 변환한다

  • http 요청 메세지의 메소드와 URI에 따라서 웹 서버 내부의 동작이 달라진다.
  • URI에 적힌 경로에 따라서 데이터를 얻어 응답한다.

2. CGI 프로그램을 작동하는 경우

  • 단순 HTML 문서가 아닌 해당 프로그램을 작동시켜서 프로그램이 출력하는 데이터를 클라이언트에 반송해야할 경우이다.
  • 요청 메세지 안에 처리하고자 하는 데이터를 넣어서 보낸다.
    • GET 요청일 경우 쿼리 파라미터에, POST 요청일 경우 리퀘스트 바디에 데이터가 추가된다.
  • 해당 요청 메시지가 오면 웹서버는 다음과 같이 동작한다.
    • URI에 쓰인 파일명을 조사하여 이것이 프로그램인지 판단한다. (cgi, php 등 확장자를 등록해 두고 파일명의 확장자가 이것과 일치하면 프로그램으로 간주한다.)
    • 프로그램이라면 해당 프로그램을 작동시키도록 OS에 의뢰한다.
    • 리퀘스트 메시지에서 데이터를 추출하여 작동시킨 프로그램에 건네준다.
    • 데이터를 처리한 후 출력 데이터를 웹 서버에 돌려준다. 보통 데이터는 HTML 태그를 내장한 문서이므로 이것을 응답 메세지로 클라이언트에 반송한다.

3. 웹 서버로 수행하는 액세스 제어

  • 웹 서버에서는 데이터를 특정 조건에 따라서 액세스를 제어할 수 있다.
  • 웹 서버에서 설정하는 조건은 3가지이다.
    • 클라이언트의 주소
    • 클라이언트의 도메인명
    • 사용자명과 패스워드
  • 이 조건을 판단하여 액세스가 허가된 경우에만 파일을 읽거나 프로그램을 실행한다.

4. 응답 메시지를 되돌려 보낸다

  • 최초 클라이언트가 요청 메세지를 웹 서버에 응답하는 동작과 동일하다.
  • 웹 서버가 Socket 라이브러리의 write를 호출하여 응답 메세지를 프로토콜 스택에 건네준다.
    • 응답 메시지를 어디에 보내야 할지는 어느 소켓을 사용하여 통지할지를 나타내는 디스크립터를 통지하여 상대를 지정한다.
  • 프로토콜 스택은 데이터를 패킷 길이에 맞게 분할하고 헤더를 붙여 패킷을 송출한다.
  • 패킷은 스위치나 라우터를 경유하여 인터넷을 통해 클라이언트에 도착한다.

웹 브라우저가 응답 메시지를 받아 화면에 표시한다

1. 응답 데이터의 형식을 보고 본질을 판단한다

  • 클라이언트는 웹 서버에서 보낸 응답 패킷을 수신한다.
    • LAN 어댑터가 신호로부터 디지털 데이터로 되돌리고
    • 프로토콜 스택이 분할된 패킷을 모아 데이터 부분을 추출하여 원래의 응답 메시지로 되돌린 후 이것을 브라우저에 건네준다.
  • 이후 브라우저의 화면 표시 동작으로 진행한다

화면 표시 동작 과정

  • 응답 메시지에 저장된 데이터의 종류를 조사한다
    • 문장, 화상, 음성, 영상 …
  • 데이터의 종류를 판단한다.
    • 응답 메시지 헤더의 Content-Type 값으로 판단한다. 값은 MIME 사양으로 종류가 규정 되어있다.
    • 데이터 종류가 텍스트인 경우 charset으로 문자 코드를 판단한다.
  • 압축 기술이나 부호화 기술에 따라서 변환 여부를 조사한다.
    • 헤더의 Content-Encoding 값으로 판단한다.
  • 요청 파일의 확장자를 통해 데이터를 판단하기도 한다.

2. 브라우저 화면에 웹 페이지를 표시하여 액세스를 완료한다

  • HTML 문서, 일반 텍스트, 화상 등 기본 데이터의 경우 브라우저 자체가 화면 표시 기능을 가지고 있으므로 브라우저가 자체에서 화면 표시 동작을 실행한다.
    • HTML의 경우 그 태그의 의미를 해석하여 OS가 어느 위치에 어떻게 표시할지 지시한다.
    • JPEG나 GIF 형식의 화상 데이터는 압축을 풀고 건네준다.
  • 관련된 응답 데이터 중 소프트웨어 어플리케이션 데이터는 해당 애플리케이션을 호출한다.
This post is licensed under CC BY 4.0 by the author.