STORY 1. HTTP 리퀘스트 메시지를 작성한다
1. 탐험 여행은 URL 입력부터 시작한다
- URL은 http:// 만 있지 않고, ftp:// 등 다양하게 있다.
http://user:password@www.cyber.co.kr:80/dir/file1.htm
http: - 프로토콜 명
user - 사용자 명 (생략 가능)
password - 패스워드 (생략 가능)
www.cyber.co.kr - 웹 서버의 도메인 명
80 - 포트 번호 (생략 가능)
/dir/file1.htm - 파일의 경로명
2. 브라우저는 먼저 URL을 해독한다
- URL의 요소
- http: + // + 웹 서버명 + / + 디렉토리명 + / + 파일명
- http: - 프로토콜
- // - 나중에 이어지는 문자열이 서버의 이름임을 나타냄
- /디렉토리명/파일명 - 경로를 나타냄 (생략 가능)
3. 파일명을 생략한 경우
4. HTTP의 기본 개념
- HTTP : HyperText Transfer Protocol
- 클라이언트 → 서버 로 리퀘스트 메시지 보냄
- 리퀘스트 메시지 안에는 무엇을, 어떻게 해서 가 있음
- 무엇을 의 경우 URI 를 나타냄 → 액세스 대상을 총칭
- 어떻게 해서 의 경우 메소드를 나타냄 (GET, POST, PUT 등)
- 서버가 이를 받아 처리 후, 응답 메시지를 보냄
- 클라이언트에 응답 메시지 도착 후 화면에 표시
- GET 메소드
- 웹 서버에 접근하여 페이지의 데이터를 읽을 때 사용
- POST 메소드
- 폼에 데이터를 사용해서 웹 서버에 송신하는 경우 사용
5. HTTP 리퀘스트 메시지를 만든다
<메소드><공백><URI><공백><HTTP 버전>
<필드명>:<필드값>
...
<공백 행>
<메시지 본문>
6. 리퀘스트 메시지를 보내면 응답이 되돌아온다
<HTTP 버전><공백><스테이터스 코드><공백><응답 문구>
<필드명>:<필드값>
...
<공백 행>
<메시지 본문>
- 스테이터스 코드
- 1xx : 처리 경과 상황
- 2xx : 정상 종료
- 3xx : 무언가 다른 조치 필요
- 4xx : 클라이언트 오류
- 5xx : 서버 오류
- 리퀘스트 메시지에 쓰는 URI는 하나뿐 → 복수 파일을 읽을 경우 별도의 리퀘스트 메시지를 보내야함
STORY 2. 웹 서버의 IP 주소를 DNS 서버에 조회한다
1. IP 주소의 기본
- TCP/IP 는 서브넷이라는 작은 네트워크를 라우터로 접속하여 전체 네트워크가 만들어짐
- 서브넷 : 간단하게 허브에 몇개의 컴퓨터가 달려 있는 형태 → 하나의 단위로써 서브넷이라고 명명
- oo동 oo번지 형태 : oo동을 서브넷에, oo번지를 컴퓨터에 할당 → 이것이 네트워크 주소
- oo동 - 네트워크 번호, 번지 - 호스트 번호 → 두개 합쳐서 IP 주소
- 송신 시작 → 허브(서브넷) → 라우터 → … → 라우터 → 서브넷 → 메시지 도착
- IP 주소 : 32비트 → 1바이트씩 10진수로 표기
- 어느 부분이 네트워크 번호인지, 호스트 번호인지 판단 불가 → 넷마스크 필요
- 10.11.12.13/255.255.255.0 → 오른쪽이 넷마스크 → 비트가 1이면 네트워크 번호, 0이면 호스트 번호를 나타냄
- 호스트 번호가 모두 0 → 서브넷 자체, 모두 1 → 브로드캐스트
2. 도메인명과 IP 주소를 구분하여 사용하는 이유
- 도메인명은 최대 255바이트까지 가능, IP 주소는 무조건 4바이트 → 훨씬 효율적
- 도메인명 → IP 주소로 바꿔주는 것이 필요함 → DNS
3. Socket 라이브러리가 IP 주소를 찾는 기능을 제공한다
- DNS 서버를 조회
- DNS 클라이언트가 DNS 서버에게 조회 요청 → 응답
- DNS 클라이언트 → DNS 리졸버 혹은 리졸버
- Socket 라이브러리 : OS에 포함된 네트워크 기능을 어플리케이션에서 호출하기 위한 부품을 모아놓은 것
- 이 라이브러리 안에 리졸버가 있음
4. 리졸버를 이용하여 DNS 서버를 조회한다
- gethostbyname(”도메인명”) 호출을 통해 결과를 받고, 여기서 IP 주소를 파싱하면 끝
STORY 3. 전 세계의 DNS 서버가 연대한다
1. DNS 서버의 기본 동작
- 클라이언트에서 조회 메시지를 받고 내용에 응답
- 조회 메시지
- 이름
- 클래스 : 인터넷 이외의 네트워크를 위해 존재, 지금은 인터넷밖에 안 쓰므로 ‘IN’ 이 입력됨
- 타입 : A면 IP 주소, MX면 메일 배송 목적지
2. 도메인의 계층
- www.naver.com 에서 뒤부터 큰 범위를 다룸
- com 아래에 naver, naver 밑에 www
- 이렇게 하나의 부서에 해당하는 것을 도메인이라고 함
- 하나의 DNS 서버 당 하나의 도메인을 등록한다고 가정
3. 담당 DNS 서버를 찾아 IP 주소를 가져온다
- 최상위 도메인(com, kr 등) 위에 루트 도메인 존재
- 상위 도메인은 아래 도메인의 주소를 가지고 있음
- 주소가 없을 시, 루트 도메인 검색 → 하위 도메인 주소를 재귀적으로 찾으면서 도달
4. DNS 서버는 캐시 기능으로 빠르게 회답할 수 있다
- 현실에서는 하나의 DNS 서버 당 하나의 도메인을 등록하지 않고, 상위 하위 도메인을 같은 DNS 서버에 등록하는 경우도 많음
- 또한 한번 조사한 이름을 캐시에 등록하여 바로 리턴하는 경우도 있음
- 캐시 주의점
- 캐시 정보 등록 후 변경되는 경우 존재 → 유효 기간을 정하여 이 기간이 지나면 캐시에서 삭제
STORY 4. 프로토콜 스택에 메시지 송신을 의뢰한다
1. 데이터 송수신 동작의 개요
- 대상 웹 서버에 메시지를 송신할 때 OS의 프로토콜 스택에 의뢰함
- 송수신 동작을 하기 전에 파이프 연결이 필요하다
- 서버에서 소켓을 만들고, 이 소켓에 클라이언트가 연결을 한다.
- 소켓을 만듦 (소켓 작성 단계)
- 서버측의 소켓에 파이프 연결 (접속 단계)
- 데이터 송수신 (송수신 단계)
- 파이프를 분리하고 소켓 말소 (연결 끊기 단계)
2. 소켓의 작성 단계
- socket() - 소켓 준비
- connect() - 접속
- write() - 송신 / read() - 수신
- close() - 연결 끊기
- socket() 호출 시 소켓을 만든다.
- socket() 리턴 값으로 디스크립터가 돌아오는데, 이는 소켓을 식별하는 역할을 한다.
3. 파이프를 연결하는 접속 단계
- connect() 호출로 파이프를 연결한다
- 인자로 디스크립터, 서버의 IP 주소, 포트 번호를 지정한다.
- IP 주소가 이미 있는데 포트 번호를 또 지정해야하는 이유는?
- IP 주소는 서버 컴퓨터까지의 도달만을 책임진다
- 따라서 소켓까지는 지정할 수 없다.
- 이 때 포트 번호가 필요하다.
- 웹의 경우 80번 포트를 사용한다.
- 디스크립터 vs IP 주소 및 포트 번호
- 디스크립터 : 애플리케이션이 소켓을 식별
- IP 주소 및 포트 번호 : 클라이언트와 서버 간에 상대의 소켓 식별
4. 메시지를 주고받는 송수신 단계
- write() - 송신
- HTTP Request 메시지를 만들고, 디스크립터와 해당 데이터를 write()를 통해 송신
- 그 후 프로토콜 스택이 서버에게 송신
- read() - 수신
- 프로토콜 스택이 수신 버퍼에서 데이터를 읽어옴
5. 연결 끊기 단계에서 송수신이 종료된다
- close() 호출 시 소켓 사이를 연결한 파이프가 없어지고 소켓도 말소됨
- HTTP에서는 서버가 연결을 끊음
- 서버가 close() 호출 → 클라이언트에게 종료 알림
- 클라이언트는 read() 호출 시 종료 알림을 읽게 됨
- 이를 통해 종료를 알게 되고, 클라이언트에서도 close() 호출하여 연결 끊음
- 원래 HTTP는 한개의 데이터마다 접속, 송신, 수신, 연결 끊기를 반복했음(non-persistent)
- 그러나 너무 비효율 → HTTP 1.1에서는 연결 끊지 않고 복수의 데이터 주고받음 (persistent)
https://product.kyobobook.co.kr/detail/S000000559964