[Week07] proxy-lab 매뉴얼

ella·2023년 4월 14일
1

🌳정글 6기🌳

목록 보기
5/39

정글에서 준 CMU 과제 중 하나인 proxy-lab 안내문이다.
코딩을 시작하기 앞서 이번에 주어진 proxy-lab 드라이버에 대해 요목조목 뜯어보고 이해해보고 가려고한다.

먼저 서버-클라이언트 모델부터 시작해보자.

컴퓨터와 컴퓨터 연결의 모델은 위 사진처럼 데이터 서비스를 제공하는 server와 데이터 서비스를 받는 client로 이루어져 있다. server는 한명이라도, client는 여러 명일 수 있다. 이를 코드 다이어그램으로 나타내면 아래와 같다.

server 컴퓨터는 open_listenfd()함수를 통해 client에서 연결 요청(connection request)을 받을 준비를 한다. 연결 요청이 들어오면, doit()이라는 함수를 통해 원하는 서비스를 제공해주고, close 명령이 들어오면 커널단에서 EOF를 감지하고 doit()함수를 리턴하고, 다시 client에서 요청이 오기를 대기한다.

해당 모델이 네트워크 응용프로그램의 기본적인 개요이며, 아래는 서버모델을 코드로 구현해보고, 개선하는 드라이버 코드 설명문의 번역 및 나의 코멘트이다.

1. introduction

웹 프록시는 웹 브라우저와 엔드 서버 사이의 중간자 역할을 하는 프로그램입니다. 웹 페이지를 가져오기 위해 브라우저가 엔드 서버에 직접 연결하는 대신, 브라우저는 프록시에 연결하여 요청을 전달합니다. 엔드 서버가 프록시에 응답하면, 프록시는 해당 응답을 브라우저에게 전달합니다.

다음 이미지는 IT위키에서 프록시 설명을 위해 나타낸 그림이다. 오른쪽의 client단에서 서비스 요청(1. 요청)을 하면, proxy 서버에 전달되고, proxy서버는 해당 요청을 server에 전달(2.요청 전송)을 한다. server는 open_listenfd()함수를 실행시키고 client단(또는 proxy단)에서 요청이 들어오기를 기다렸다가 이를 수락한다(3. 요청 접수). 요청대로 원하는 데이터를 만들고(4. 응답 생성) proxy단으로 응답을 전송한다. proxy는 이를 client에게 전달하며(5. 응답 전송), client는 이를 수신한다(6.응답 수신).

얼핏 본다면 서버와 클라이언트 사이에서 proxy는 전달자 역할밖에 안하는 것같다. 그런데 왜 proxy가 필요한 걸까. 그 이유는 다음 글에서 설명해 준다.

프록시는 여러 목적으로 사용됩니다. 때로는 방화벽에서 프록시를 사용하여 방화벽 뒤에 있는 브라우저가 방화벽을 통해 외부 서버에만 연결할 수 있도록 합니다. 프록시는 익명화 기능으로도 사용됩니다. 모든 식별 정보를 제거하면 브라우저를 웹 서버에 대해 익명으로 만들 수 있습니다. 프록시는 웹 객체 캐싱을 위해 사용될 수도 있습니다. 로컬에 객체의 사본을 저장함으로써, 프록시는 원격 서버와 통신하는 대신 캐시에서 객체를 읽어서 미래 요청에 응답할 수 있습니다.


이 실습에서는 웹 객체를 캐시하는 간단한 HTTP 프록시를 작성합니다. 첫 번째 파트에서는 프록시를 설정하여 들어오는 연결을 수락하고 요청을 읽고 구문 분석하며, 요청을 웹 서버에 전달하고 서버의 응답을 읽고 해당 클라이언트에게 응답을 전달합니다. 이 첫 번째 파트에서는 기본적인 HTTP 작동 방식과 소켓을 사용하여 네트워크 연결을 통신하는 프로그램을 작성하는 방법에 대해 배우게 됩니다. 두 번째 파트에서는 프록시를 업그레이드하여 동시에 여러 연결을 처리할 수 있도록 업그레이드합니다. 이를 통해 시스템에서 중요한 동시성 개념을 다루게 됩니다. 세 번째 파트에서는 최근에 액세스한 웹 콘텐츠의 단순한 메모리 캐시를 사용하여 프록시에 캐싱을 추가합니다.

3. Handout instructions

이번 프록시 랩에서는 학생들에게 proxylab-handout.tar 파일을 배포할 것입니다. 강사는 이 파일을 보호된 디렉토리에 복사한 다음 다음 명령을 실행하여 학생들에게 전달할 것입니다.


linux> tar xvf proxylab-handout.tar


위 명령은 proxylab-handout 디렉토리를 생성합니다. README 파일에는 해당 파일들의 각각의 역할이 설명되어 있습니다.

해당 설명은 linux환경에서 cli를 통해 드라이버파일을 다운받는 방법이다.

4. Part I: Implementing a sequential web proxy

첫 번째 단계는 HTTP/1.0 GET 요청을 처리하는 기본 순차 프록시를 구현하는 것입니다. POST와 같은 다른 요청 유형은 선택 사항입니다.


프록시가 시작되면, 지정된 포트 번호에서 들어오는 연결을 수신 대기해야 합니다. 연결이 설정되면, 프록시는 클라이언트에서 요청 전체를 읽고 요청을 구문 분석해야 합니다. 클라이언트가 유효한 HTTP 요청을 보냈는지 여부를 확인해야 합니다. 그러면 적절한 웹 서버에 대한 연결을 자체적으로 설정하고 클라이언트가 지정한 객체를 요청해야 합니다. 마지막으로, 프록시는 서버의 응답을 읽고 클라이언트에게 전달해야 합니다.

proxy가 해야할 일:
1. 지정된 포트 번호에서 client 연결 수신 대기
2. 연결시, 요청 구문 분석 - HTTP가 유효한 요청인지 확인
3. 적절한 웹서버 연결인 경우, 연결 설정 및 server단에 객체 요청
4. 서버의 응답을 읽고, 클라이언트에 전달

4.1 HTTP/1.0 GET requests
사용자가 웹 브라우저의 주소 표시줄에 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 요청의 모든 줄이 개행 문자('\n') 바로 앞에 캐리지 리턴('\r')으로 끝난다는 점과 HTTP 요청이 빈 줄("\r\n")로 끝나야 한다는 점도 중요합니다.


위의 예제에서 웹 브라우저의 요청 줄은 HTTP/1.1로 끝나지만 프록시의 요청 줄은 HTTP/1.0으로 끝납니다. 최신 웹 브라우저는 HTTP/1.1 요청을 생성하지만 프록시는 이를 처리하고 HTTP/1.0 요청으로 전달해야 합니다.


HTTP 요청, 심지어 HTTP/1.0 GET 요청의 하위 집합조차도 매우 복잡할 수 있으므로 고려해야 할 사항이 중요합니다. 교재에서는 HTTP 트랜잭션의 일부 세부 정보를 설명하지만, RFC 1945를 참조하여 HTTP/1.0 사양을 완전히 확인해야 합니다. 이상적으로, HTTP 요청 파서는 RFC 1945의 관련 섹션에 따라 완전히 견고해야 합니다. 다만, 명세서는 여러 줄로 된 요청 필드를 허용하지만 프록시는 이를 제대로 처리하지 않아도 됩니다. 물론 프록시는 잘못된 요청으로 인해 예기치 않게 중단되어서는 안 됩니다.

Tiny.c는 항상 HTTP/1.0 요청만 수락한다.
Microsoft Edge의 bing을 이용해서 알아본 바는 다음과 같다. (세상 살기 편해졌다.)
"Microsoft Edge는 HTTP/1.1을 지원합니다. HTTP/1.0은 오래된 버전의 HTTP 프로토콜이며, 현재 사용되지 않는 기능이 많습니다. 따라서 HTTP/1.0을 사용하는 웹 사이트는 Microsoft Edge에서 제대로 작동하지 않을 수 있습니다."

따라서 위 설명처럼 웹브라우저 요청 줄은 HTTP/1.1로 보내지지만, 프록시에서 요청을 HTTP/1.0으로 변경해서 요청을 전달해야 한다.

4.2 Request headers

이번 lab에서는 HTTP/1.0 GET 요청을 처리하는 기본적인 sequential 프록시를 구현해야 합니다. 프록시가 실행되면, 지정된 포트 번호를 사용하여 들어오는 연결을 수신해야 합니다. 연결이 설정되면, 프록시는 클라이언트에서 요청을 모두 읽고 구문 분석해야 합니다. 클라이언트가 유효한 HTTP 요청을 보냈는지 확인해야 합니다. 유효한 경우, 프록시는 적절한 웹 서버에 대한 연결을 자체적으로 설정한 다음, 클라이언트에서 지정한 객체를 요청해야 합니다. 마지막으로, 프록시는 서버의 응답을 읽고 해당 응답을 클라이언트에게 전달해야 합니다.


RFC 1945의 적절한 섹션에 따라 HTTP 요청을 완전히 robust하게 파싱해야 하지만, 멀티라인 요청 필드를 제대로 처리할 필요는 없습니다. 또한, RFC 1945에서는 "\r\n"로 끝나는 빈 줄로 HTTP 요청이 종료되는 것이 중요합니다.


이번 lab에서 중요한 HTTP 요청 헤더는 Host, User-Agent, Connection 및 Proxy-Connection 헤더입니다. 프록시는 항상 Host 헤더를 보내야 합니다. Host 헤더는 최종 서버의 호스트 이름을 설명합니다. 브라우저가 자체 Host 헤더를 첨부하는 경우, 프록시는 브라우저와 동일한 Host 헤더를 사용해야 합니다.


User-Agent 헤더는 클라이언트를 식별하고, 웹 서버가 제공하는 콘텐츠를 조작하는 데 사용됩니다. 프록시는 Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120305 Firefox/10.0.3과 같은 User-Agent 헤더를 보낼 수 있습니다.


Connection 및 Proxy-Connection 헤더는 요청/응답 교환 후에 연결을 계속 유지할지 여부를 지정하는 데 사용됩니다. 프록시는 각 요청마다 새로운 연결을 열 것이 권장되므로, 이러한 헤더의 값으로 close를 지정해야 합니다.


마지막으로, 브라우저가 HTTP 요청의 일부로 추가 요청 헤더를 보내는 경우, 프록시는 이러한 헤더를 변경하지 않고 그대로 전달해야 합니다.

proxy header에 대한 간략한 설명이다.

4.3 Port numbers

HTTP 요청 포트는 HTTP 요청의 URL에 선택적인 필드입니다. 즉, URL이 http://www.cmu.edu:8080/hub/index.html과 같은 형식인 경우, 프록시는 기본 HTTP 포트인 포트 80이 아니라 호스트 www.cmu.edu의 포트 8080에 연결해야 합니다. 프록시는 URL에 포트 번호가 포함되어 있는지 여부에 관계없이 올바르게 작동해야 합니다.

URL에 특정 포트가 표기되었을 때는 기본 포트가 아니라 특정포트로 연결되어야 한다.

수신 대기 포트는 프록시가 들어오는 연결을 대기해야 하는 포트입니다. 프록시는 수신 대기 포트 번호를 지정하는 명령 행 인수를 받아야 합니다. 예를 들어 다음 명령으로 프록시는 포트 15213에서 연결을 수신해야 합니다.


linux> ./proxy 15213

(주의!! 이건 127.0.0.1은 로컬호스트 주소다. 나처럼 윈도우 환경의 wsl를 사용하는 등 로컬호스트 환경에서 사용할 수 있다. AWS 빌려서 하는 사람은 다른 방법을 찾아보길 바란다.)
비슷한 예로 처음 tiny.c를 실행시켜보고 싶으면, 다음과 같이 특정 port번호로 tiny서버를 실행시키고,

일반 브라우저에서

http://127.0.0.1:8888/

url로 실행시키면 tiny가 브라우저로 실행되는걸 볼수 있다.

권한이 없는 수신 대기 포트(1024보다 크고 65,536보다 작음) 중에서 원하는 포트 번호를 선택할 수 있습니다. 프록시마다 고유한 수신 대기 포트를 사용해야 하며, 여러 명이 동시에 사용할 예정이므로 스크립트 port-for-user.pl을 사용하여 개인적인 포트 번호를 선택하는 것이 좋습니다. 이 스크립트를 사용하여 사용자 ID를 기반으로 포트 번호를 생성합니다.


linux> ./port-for-user.pl droh
droh: 45806


port-for-user.pl이 반환하는 포트 p는 항상 짝수입니다. 따라서 Tiny 서버와 같은 추가 포트 번호가 필요한 경우 p 및 p + 1 포트를 안전하게 사용할 수 있습니다.


임의의 포트 번호를 선택하지 마십시오. 그렇게 하면 다른 사용자와 충돌할 위험이 있습니다.

5 Part II: Dealing with multiple concurrent request

이전에 구현한 기본적인 sequential proxy가 정상 동작하면, 이제 여러 요청을 동시에 처리할 수 있도록 변경해야 합니다. 가장 간단한 동시성 서버 구현 방법은 각 새 연결 요청마다 새 스레드를 생성하는 것입니다. 다른 설계 방법도 가능합니다. 예를 들어, 교재 12.5.5 절에서 설명하는 프리스레드 서버 등이 있습니다.


스레드는 메모리 누수를 방지하기 위해 분리된 모드에서 실행되어야 합니다.
CS:APP3e 교재에서 설명하는 open clientfd와 open listenfd 함수는 모던하며 프로토콜 독립적인 getaddrinfo 함수를 기반으로 하므로 스레드 안전합니다.

6 Part III: Caching web objects

이번 랩에서는 프록시에 최근 사용된 웹 객체를 메모리에 저장하는 캐시를 추가합니다. HTTP는 실제로 웹 서버가 서빙하는 객체가 캐시되어야 하는 방법과 클라이언트가 캐시를 사용하는 방법에 대해 상당히 복잡한 모델을 정의합니다. 그러나 이번 랩에서는 간소화된 방법을 채택합니다. 프록시가 서버로부터 웹 객체를 수신하면 객체를 캐시에 저장하고, 클라이언트에게 전송하는 동안 캐시합니다. 다른 클라이언트가 동일한 객체를 동일한 서버에서 요청하면, 프록시는 서버에 다시 연결할 필요 없이 캐시된 객체를 간단히 재전송할 수 있습니다. 당연히 프록시가 요청되는 모든 객체를 캐시하면, 무제한의 메모리가 필요합니다. 또한, 일부 웹 객체는 다른 것보다 크기 때문에, 하나의 거대한 객체가 캐시 전체를 소비하여 다른 객체들이 전혀 캐시되지 못하는 경우가 발생할 수 있습니다. 이러한 문제를 피하기 위해 프록시에는 최대 캐시 크기와 최대 캐시 객체 크기가 있어야합니다.


6.1 Maximum cache size
당신의 프록시 캐시의 전체 크기는 다음과 같아야합니다:
MAX_CACHE_SIZE = 1 MiB
캐시 크기를 계산할 때 프록시는 실제 웹 객체를 저장하는 데 사용되는 바이트 만 계산해야합니다. 메타데이터를 포함한 기타 바이트는 무시해야합니다.


6.2 Maximum object size
프록시에 캐시를 추가하여 최근에 사용된 웹 오브젝트를 메모리에 저장해야 합니다. HTTP는 실제로 웹 서버에서 제공되는 오브젝트가 캐싱되어야 하는 방법과 클라이언트가 대신 캐시를 사용해야 하는 방법을 상세히 정의합니다. 그러나 여기서는 단순화된 방법을 적용합니다.


프록시가 서버로부터 웹 오브젝트를 받으면, 오브젝트를 클라이언트에게 전송하는 동안 그것을 메모리에 캐시해야 합니다. 같은 서버로부터 다른 클라이언트가 동일한 오브젝트를 요청하면, 프록시는 서버에 다시 연결할 필요 없이 캐시된 오브젝트를 그대로 재전송할 수 있습니다.


물론, 모든 요청된 오브젝트를 캐시하면 메모리가 무한정 필요합니다. 또한, 일부 웹 오브젝트가 다른 것보다 크기 때문에, 하나의 큰 오브젝트가 모든 캐시를 차지하여 다른 오브젝트가 전혀 캐시되지 않을 수 있습니다. 이러한 문제를 방지하려면, 프록시는 최대 캐시 크기와 최대 캐시 오브젝트 크기 모두를 가져야 합니다.

캐시에 대한 간단명료한 설명화, 우리가 실습 때 설정해야하는 캐시 범위에 대해 정의해주고 있다.

6.3 Eviction policy

당신의 프록시 캐시는 최근에 사용되지 않은(LRU) 방침을 근사화하는 방침을 사용해야 합니다. 엄격하게 LRU일 필요는 없지만, 어느 정도 근접한 방식으로 작동해야 합니다. 객체를 읽는 것과 쓰는 것 모두 객체를 사용한 것으로 간주됩니다.

프록시 캐시에는 최근에 가장 사용되지 않은 객체를 먼저 삭제하는 방식인 LRU 방식을 적용해야 한다. 또한, 또한 캐시에 있는 객체를 읽는 것과 쓰는 것 둘 다 사용한 것으로 간주되므로, 객체를 캐시에 저장하거나 삭제할 때 두 작업 모두 고려해야 한다.

6.4 Synchronization

캐시 접근은 스레드 안전(thread-safe)해야하며, 캐시 접근이 경쟁 조건(race condition)없이 이루어지도록 보장하는 것이 이번 랩의 더욱 흥미로운 부분 중 하나일 것입니다. 사실, 특별한 요구사항으로, 다중 스레드가 동시에 캐시에서 동시에 읽을 수 있어야 합니다. 물론, 쓰기는 한 번에 한 스레드만 허용되어야 하지만, 읽기는 그러한 제한이 존재하지 않아야 합니다.


따라서, 전체 캐시에 대한 액세스를 단일 배타적 락으로 보호하는 것은 적절한 해결책이 아닙니다. 캐시를 분할하거나 Pthreads readers-writers lock을 사용하거나, 세마포어를 사용하여 직접 readers-writers solution을 구현하는 것과 같은 옵션을 고려해볼 수 있습니다. 어쨌든, 엄격한 LRU 제거 정책을 구현할 필요가 없기 때문에 여러 독자를 지원하는 유연성을 가질 수 있습니다.

7 Evaluation

이 과제는 총 70점 만점으로 채점됩니다:
• 기본 정확성: 기본 프록시 작동에 대해 40점 (자동 채점)
• 동시성: 동시 요청 처리에 대해 15점 (자동 채점)
• 캐시: 작동하는 캐시에 대해 15점 (자동 채점)

7.1 Autograding

'proxylab-handout' 디렉토리에 포함된 driver.sh라는 자동 채점기를 사용하여 BasicCorrectness, Concurrency 및 Cache 점수를 부여할 예정입니다. 다음 명령어를 실행하여 드라이버를 실행해야 합니다.
linux> ./driver.sh
드라이버는 리눅스 머신에서 실행해야 합니다.

7.2 Robustness

항상처럼, 오류나 잘못된 또는 악의적인 입력에 견고한 프로그램을 제공해야합니다. 서버는 일반적으로 장기 실행 프로세스이며, 웹 프록시도 예외가 아닙니다. 오류의 다양한 유형에 대해 장기 실행 프로세스가 어떻게 반응해야하는지 신중하게 생각하십시오. 많은 종류의 오류의 경우 프록시가 즉시 종료하는 것은 분명히 부적절합니다.
강건성은 세그멘테이션 오류 및 메모리 누수 및 파일 디스크립터 누수와 같은 오류 사례에 대한 취약성이 없어야 함을 의미합니다.

8 Testing and debugging

간단한 자동 채점 프로그램 이외에도, 구현을 테스트하기 위한 샘플 입력이나 테스트 프로그램은 제공되지 않습니다. 직접 테스트 케이스를 작성하고, 구현을 디버그하기 위한 테스트 하네스도 직접 개발해야 합니다. 이는 실제 세상에서 매우 유용한 기술입니다. 실제 운영 환경을 정확하게 알 수 없고 참조 솔루션이 종종 없기 때문입니다. 다행히도 프록시를 디버그하고 테스트하기 위해 많은 도구가 있습니다. 모든 코드 경로를 확인하고 기본 케이스, 일반 케이스 및 엣지 케이스를 포함한 대표적인 입력을 테스트하십시오.

8.1 Tiny web server

handout 디렉토리에는 CS:APP Tiny 웹 서버의 소스 코드가 포함되어 있습니다. thttpd보다는 강력하지 않지만, 필요에 따라 쉽게 수정할 수 있습니다. 또한 프록시 코드의 합리적인 시작점입니다. 그리고 드라이버 코드가 페이지를 가져 오는 데 사용하는 서버입니다.

thttpd는 작고 빠른 웹 서버로, 거의 모든 유닉스 및 리눅스 시스템에서 실행할 수 있다. thttpd는 다른 웹 서버에 비해 구성이 간단하고 유지 보수 비용이 적게 든다. 일부 기능 (예 : CGI, SSL)가 누락되어 있지만, 많은 웹 사이트에서 충분히 사용할 수 있다고 한다. thttpd는 웹 프록시 또는 트래픽 제한 도구로도 사용된다.

8.2 telnet

교재(11.5.3)에서 설명한 대로, telnet을 사용하여 프록시에 연결을 열고 HTTP 요청을 보낼 수 있습니다.

8.3 curl

curl 명령어를 사용하여 모든 서버, 포함하여 자신의 프록시에 HTTP 요청을 보낼 수 있습니다. 이는 매우 유용한 디버깅 도구입니다. 예를 들어, 프록시와 Tiny 모두 로컬 머신에서 실행되고 Tiny가 포트 15213에서 수신 대기하고 있고 프록시가 포트 15214에서 수신 대기하고 있다면 다음 curl 명령어를 사용하여 Tiny에서 페이지를 요청할 수 있습니다.

linux> curl -v --proxy http://localhost:15214 http://localhost:15213/home.html
* About to connect() to proxy localhost port 15214 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 15214 (#0)
GET http://localhost:15213/home.html HTTP/1.1
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu)...
Host: localhost:15213
Accept: */*
Proxy-Connection: Keep-Alive

* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: Tiny Web Server
< Content-length: 120
< Content-type: text/html
<
<html>
<head><title>test</title></head>
<body>
<img align="middle" src="godzilla.gif">
Dave O’Hallaron
</body>
</html>
* Closing connection #0

8.4 netcat

netcat 또는 nc는 다용도 네트워크 유틸리티입니다. telnet처럼 서버에 연결하기 위해 netcat을 사용할 수 있습니다. 예를 들어, 프록시가 포트 12345에서 실행 중인 catshark에서 실행 중인 것으로 가정한다면 다음과 같이 수동으로 프록시를 테스트할 수 있습니다.

sh> nc catshark.ics.cs.cmu.edu 12345
GET http://www.cmu.edu/hub/index.html HTTP/1.0
HTTP/1.1 200 OK

netcat은 웹 서버에 연결할 수 있는 것 외에도 자체적으로 서버로 동작할 수 있습니다. 다음 명령을 사용하여 포트 12345에서 수신 대기 중인 netcat 서버를 실행할 수 있습니다.
sh> nc -l 12345

netcat 서버를 설정하면 프록시를 통해 가짜 객체에 대한 요청을 생성하고 프록시가 netcat에게 보낸 정확한 요청을 검사할 수 있습니다.

8.5 Web browsers

Mozilla Firefox의 최신 버전을 사용하여 프록시를 테스트해야합니다. Firefox에 방문하여 Firefox 정보를 확인하면 브라우저를 최신 버전으로 업데이트 할 수 있습니다.


Firefox를 프록시와 함께 사용하도록 구성하려면 Preferences>Advanced>Network>Settings를 방문하십시오.


실제 웹 브라우저를 통해 프록시가 작동되는 것을 볼 수 있으므로 매우 흥미롭게 느껴질 것입니다. 프록시의 기능은 제한될 수 있지만 대부분의 웹 사이트를 프록시를 통해 탐색할 수 있다는 것을 알게될 것입니다.


중요한 주의 사항은 웹 브라우저를 사용하여 캐시를 테스트 할 때 매우 신중해야합니다. 모든 최신 웹 브라우저에는 자체 캐시가 있으므로 프록시 캐시를 테스트하기 전에 브라우저의 캐시를 비활성화해야합니다.

9 Handin instructions

핸드인 파일을 제출하는 방법에 대한 지침은 각 학생마다 다릅니다. 이는 교수님께서 정한 방법을 따라야 합니다. 보통은 학교에서 지정한 핸드인 시스템이나 이메일 등을 통해 제출하게 됩니다.


또한, 교재의 10-12장에는 시스템 수준의 I/O, 네트워크 프로그래밍, HTTP 프로토콜 및 동시성 프로그래밍에 대한 유용한 정보가 포함되어 있습니다. 또한, HTTP/1.0 프로토콜의 완전한 사양은 RFC 1945(https://tools.ietf.org/html/rfc1945)에서 확인할 수 있습니다.

10 Hints

• 교재 10~12장은 시스템 레벨 I/O, 네트워크 프로그래밍, HTTP 프로토콜 및 동시성 프로그래밍에 대한 유용한 정보를 담고 있습니다.
• 교재 10.11절에서 설명한 대로 소켓 입출력에 표준 I/O 함수를 사용하는 것은 문제가 됩니다. 대신 handout 디렉토리에 있는 csapp.c 파일에 제공되는 Robust I/O (RIO) 패키지를 사용하는 것이 좋습니다.
csapp.c에서 제공되는 오류 처리 함수는 서버가 연결을 수락하기 시작하면 종료되지 않아야하기 때문에 프록시에 적합하지 않습니다. 이를 수정하거나 직접 작성해야합니다.
• handout 디렉토리의 파일을 원하는대로 수정할 수 있습니다. 예를 들어 모듈성을 위해 캐시 기능을 cache.c 및 cache.h 파일의 라이브러리로 구현할 수 있습니다. 물론 새 파일을 추가하려면 제공된 Makefile을 업데이트해야합니다.
• CS:APP3e 교재 964쪽의 출처에서 언급한 대로 프록시는 SIGPIPE 신호를 무시해야하며, EPIPE 오류를 반환하는 쓰기 작업을 고요하게 처리해야합니다.
• 때로는 미처 닫힌 소켓에서 바이트를 수신하기 위해 read를 호출하면 read가 ECONNRESET으로 설정된 errno와 함께 -1을 반환할 수 있습니다. 프록시는 이 오류로 인해 종료되어서는 안됩니다.
• 웹 상의 모든 콘텐츠가 ASCII 텍스트는 아닙니다. 이미지 및 비디오와 같은 바이너리 데이터가 대부분입니다. 네트워크 I/O에 대한 함수를 선택하고 사용할 때 바이너리 데이터를 고려해야합니다.
• 원래 요청이 HTTP/1.1인 경우에도 모든 요청을 HTTP/1.0으로 전달합니다.

Good luck!

예외문에 대한 추가 정보들이 주어진다.


갈 길이 멀다..! 내일부터는 tiny.c 코드와 함께 돌아오겠다.

profile
^^*

0개의 댓글