-
CSAPP : 웹서버 만들기(Week07) - Proxy 1,2(Sequential, Concurrent)개발/Proxy 2022. 5. 26. 22:46
Part 1. Sequential Web Proxy
sequential web proxy는 한 번에 하나씩 요청을 처리하는 웹 서버이다. 트랜잭션이 완료되면 다음 커넥션이 처리한다. 처리 도중에 모든 다른 커넥션이 무시되므로 심각한 성능 문제를 만들어낸다.
기본 HTTP 작업과 소켓을 사용하여 네트워크 연결을 통해 통신하는 프로그램을 작성하는 방법에 대한 학습이 포함된다.
Sequential Web Proxy 구현
목표
- basic sequential proxy that handles HTTP/1.0 GET requests
- read the entirety of the request from the client and parse the request.
- establish its own connection to the appropriate web server then request the object the client specified.
- proxy should read the server’s response and forward it to the client.
순서
- HTTP/1.0 GET 요청을 처리하는 기본 순차 프록시를 구현하는 것. POST는 선택사항
- 프록시는 명령줄에 번호가 지정될 포트에서 들어오는 연결을 수신 대기해야한다.
- 연결이 설정되면 프록시가 클라이언트의 전체 요청을 읽고 요청을 구문 분석해야한다.
- 클라이언트가 유효한 HTTP 요청을 보냈는지 여부를 결정해야한다.
- 적절한 웹서버에 대한 자체 연결을 설정한 다음 지정된 클라이언트를 요청할 수 있습니다.
- 마지막으로 프록시는 서버의 응답을 읽고 클라이언트에게 전달해야한다.
1. HTTP/1.0 GET 요청
- 최종 사용자가 http://www.cmu.edu/hub/index.html과 같은 URL을 웹 브라우저의 주소 표시줄에 입력하면 브라우저는 다음 줄로 시작하는 HTTP 요청을 프록시에 보낸다.
GET http://www.cmu.edu/hub/index.html HTTP/1.1
- 이 경우 프록시는 요청을 최소한 다음 필드로 구문 분석해야 한다.
- 호스트 이름 : www.cmu.edu
- 경로 또는 쿼리 및 그 뒤에 오는 모든것 : /hub/index.html
- 프록시는 www.cmu.edu에 대한 연결을 열고 다음 형식의 줄로 시작하는 자체 HTTP 요청을 보내야 하는지 결정할 수 있다.
GET /hub/index.html HTTP/1.0
- HTTP 요청의 모든 줄은 캐리지 리턴 ‘\r’로 끝나고 그 뒤에 줄 바꿈 ‘\n’이 온다.
- 또한, 중요한 것은 모든 HTTP 요청이 “\r\n”이라는 빈 줄로 종료된다는 것이다.
- 위의 예에서 웹 브라우저의 요청 라인은 HTTP/1.1로 끝나는 반면 프록시의 요청 라인은 HTTP/1.0으로 끝이난다. 최신 웹브라우저는 HTTP/1.1 요청을 생성하지만 프록시는 이를 처리하고 HTTP/1.0 요청으로 전달해야한다.
- HTTP/1.0 GET 요청의 하위 집합일지라도 HTTP 요청은 엄청나게 복잡할 수 있다는 점을 고려한느 것이 중요하다
- 교과서는 HTTP의 트랜잭션의 특정 세부사항을 설명하지만 전체 HTTP/1.0 사양은 RFC 1945를 참조해야한다
- 물론 프록시가 잘못된 요청으로 인해 조기 중단되어서는 안된다.
2. 요청 헤더
이 실습의 중요한 요청 헤더는 Host, User-Agent, Connection 및 Proxy-Connection 헤더이다.
2-1) Host
- 항상 호스트 헤더를 보낸다.
- 호스트 헤더는 최종 서버의 호스트 이름을 설명한다. 예를 들어 http://www.cmu.edu/hub/index.html 에서 프록시는 다음 헤더를 보낸다
호스트 : www.cmu.edu
- 웹 브라우저가 자신의 호스트 헤더를 HTTP 요청에 첨부할 수 있다. 이 경우 프록시는 브라우저와 동일한 호스트 헤더를 사용해야한다.
2-2) User-Agent
- 항상 다음 User-Agent 헤더를 보내도록 선택할 수 있다.
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3)
Gecko/20120305 Firefox/10.0.3- 헤더는 작성에서 한 줄로 맞지 않기 때문에 두 개의 별도 줄에 제공되지만 프록시는 헤더를 한 줄로 보내야 한다.
- User-Agent 헤더는 클라이언트를 식별하고(운영 체제 및 브라우저와 같은 매개변수 측면에서) 웹 서버는 종종 식별 정보를 사용하여 제공하는 콘텐츠를 조작한다. 이 특정 User-Agent:string을 보내면 내용과 다양성 면에서 간단한 Telnet 스타일 테스트 중에 반환되는 자료를 개선할 수 있다.
- 편의를 위해 User-Agent 헤더의 값이 proxy.c에서 문자열 상수로 제공된다.
2-3) Connection
Connection: close
2-4) Proxy-Connection: close
Proxy-Connection: close
- Connection 및 Proxy-Connection 헤더는 첫 번째 요청/응답 교환이 완료된 후 연결을 유지할 지 여부를 지정하는데 사용한다.프록시가 각 요청에 대해 새 연결을 열도록 하는 것은 완벽하게 허용된다. 이러한 헤더 값으로 close를 지정하면 첫 번째 요청/응답 교환 후 프록시가 연결을 닫으려는 것을 웹 서버에 알린다.
- 브라우저가 HTTP 요청의 일부로 추가 요청 헤더를 보내는 경우 프록시는 변경하지 않고 헤더를 전달해야한다.
3. Port Number
- 이 실습에는 HTTP 요청 포트와 프록시의 수신 포트라는 두 가지 중요한 포트 번호 클래스가 있다.
- HTTP 요청 포트는 HTTP 요청 URL의 선택적 필드이다. 즉, URL은 http://www.cmu.edu:8080/hub/index.html 형식일 수 있다. 이 경우 프록시는 포트 8080 대신 www.cmu.edu 호스트에 연결해야 한다. 기본 HTTP 포트는 80이다 프록시는 URL에 포트 번호가 포함되어 있는지 여부에 관계 없이 제대로 동작해야 한다.
- 수신 포트는 프록시가 들어오는 연결을 수신해야 하는 포트이다. 프록시는 프록시의 수신 포트 번호를 지정하는 명령줄 인수를 수락해야한다. 예를 들면 다음 명령을 사용하면 프록시가 포트 15213에서 연결을 수신 대기해야한다.
linux> ./proxy 15213
- 다른 프로세스에서 사용하지 않는 한 권한 없는 수신 포트 (1024 초과 65536 미만)를 선택가능
- 각 프록시는 고유한 수신 포트를 사용해야하고 많은 사람들이 각 시스템에서 동시에 작업하기 때문에 자신의 개인 포트를 선택하는 데 도움이 되도록 port-for-user.pl 스크립트가 제공된다. 이를 사용하여 사용자 ID를 기반으로 포트 번호를 생성한다.
linux> ./port-for-user.pl droh droh:45806
- port-for-user.pl이 반환하는 포트 p는 항상 짝수이다. 따라서 Tiny 서버의 경우와 같이 추가 포트 번호가 필요한 경우 포트 p 및 p+1을 안전하게 사용할 수 있다.
- 임의 포트를 선택하지 마라. 그렇게 하면 다른 user를 방해할 위험이 있다.
Part2. Dealing With multiple concurrent requests
- 동작하는 Sequential Proxy가 있으면 여러 요청을 동시에 처리하도록 변경
- 동시 서버를 구현하는 가장 간단한 방법은 각각의 새 연결 요청을 처리하기 위해 새 Thread를 생성하는 것입니다.
- 메모리 누수를 방지하려면 스레드를 분리 모드에서 실행해야 한다.
- CSAPP 교과서에 설명된 Open Clientfd 및 Open listenfd 기능은 최신 프로토콜과 독립적인 getaddrinf 기능을 기반으로 하므로 스레드로부터 안전하다.
'개발 > Proxy' 카테고리의 다른 글
CSAPP : 웹서버 만들기(Week07) - Proxy 3(Caching) (0) 2022.05.26 CSAPP : 웹서버 만들기(Week07) - Proxy 개념 (0) 2022.05.26