[C 언어] CSAPP 11장 Homework 구현

유선·2024년 4월 20일
0

CS

목록 보기
20/25
post-thumbnail

💡 csapp (번역본) 930p
11.6.c / 11.7 / 11.9 / 11.11
풀이 및 구현입니다.

전체 코드

source code 👩🏻‍💻

11.6.c

Tiny의 출력을 조사해서 여러분이 사용하는 브라우저의 HTTP 버전을 결정하라.



=> HTTP/1.0 or HTTP/1.1
=> 왜 response, request 버전이 다른가,,,?

11.7

Tiny를 확장해서 MPG 비디오 파일을 처리하도록 하시오. 실제 브라우저를 사용해서 여러분의 결과를 체크하시오.

1. get_filetype: MP4 비디오 타입 추가

  else if (strstr(filename, ".mp4"))
    strcpy(filetype, "video/mp4");
  • tiny/tiny.c -> get_filetype에 추가

2. MP4 비디오 추가

비디오 추가

3. home.html: MP4 실행을 위한 태그 구현

<html>
<head><title>test</title></head>
<body> 
<img align="middle" src="godzilla.gif">
Dave O'Hallaron

<video src="video.mp4" controls loop autoplay width="550"></video>
</body>
</html>
  • home.html에 추가

4. 결과 화면

11.9

Tiny를 수정해서 정적 컨텐츠를 처리할 때 요청한 파일을 mmap과 r1o_readn 대신에
malloc, rio_readn, rio_writen을 사용해서 연결 식별자에게 복사하도록 하시오.

1. mmap 제거하고 malloc으로 변경하기

srcp = (char *) malloc(filesize); // mmap 대신 malloc 사용

2. rio_readn 사용하기

rio_readn(srcfd, srcp, filesize);

3. munmap 제거하고 free로 변경하기

free(srcp);

  • tiny/tiny.c => serve_static에서 변경

4. 결과 화면


calculate 클릭!

11.10

A. 그림 11.27의 CGI adder함수에 대한 HTML 형식을 작성하시오. 이 형식은 사용
자가 함께 더할 두 개의 숫자로 채우는 두 개의 텍스트 상자를 포함해야 한다. 여 러
분의 형식은 GET 메소드를 사용해서 컨텐츠를 요청해야 한다.

B. 실제 브라우저를 사용해서 Tiny로부터 이 형식을 요청하고, 채운 형식을 Tiny에
보내고, adder가 생성한 동적 컨텐츠를 표시하는 방법으로 여러분의 작업을 체크
하라.

    if ((buf = getenv("QUERY_STRING")) != NULL) {
        p = strchr(buf, '&');
        *p = '\0';
        // strcpy(arg1, buf);
        // strcpy(arg2, p + 1);
        // n1 = atoi(arg1); // 첫 번째 인자를 정수로 변환
        // n2 = atoi(arg2); // 두 번째 인자를 정수로 변환
        /* Homework: 11.10 */
        sscanf(buf, "num1=%d", &n1);
        sscanf(p + 1, "num2=%d", &n2);
    }
  • tiny/adder.c => if문 수정
<html>
<head><title>test</title></head>
<body> 
<img align="middle" src="godzilla.gif">
Dave O'Hallaron

<video src="video.mp4" controls loop autoplay width="550"></video>
<form action="/cgi-bin/adder" method="GET">
    <p>Number 1: <input type="text" name="num1"></p>
    <p>Number 2: <input type="text" name="num2"></p>
    <input type="submit" value="Calculate">
</form>
</body>
</html>
  • tiny/home.html => 인풋 박스 추가

11.11

Tiny를 확장해서 HTTP HEAD 메소드를 지원하도록 하라. telnet을 웹 클라이언트로
사용해서 작업 결과를 체크하시오.

  /* HTTP 요청의 메서드가 "GET"이 아닌 경우에 501 오류를 클라이언트에게 반환 */
  /* Homework 11.11 "HEAD"가 아닌 경우 추가 */
  if (strcasecmp(method, "GET") * strcasecmp(method, "HEAD"))
  { // 조건문에서 하나라도 0이면 0
    clienterror(fd, method, "501", "Not implemented", "Tiny does not implement this method");
    return;
  }
 
void serve_static(int fd, char *filename, int filesize, char *method)
{
  int srcfd;                // 파일 디스크립터
  char *srcp,               // 파일 내용을 메모리에 매핑한 포인터
       filetype[MAXLINE],   // 파일의 MIME 타입
       buf[MAXBUF];         // 응답 헤더를 저장할 버퍼

  /* 응답 헤더 생성 및 전송 */
  get_filetype(filename, filetype);                         // 파일 타입 결정
  sprintf(buf, "HTTP/1.0 200 OK\r\n");                      // 응답 라인 작성
  // 응답 헤더
  sprintf(buf, "%sServer: Tiny Web Server\r\n", buf);       // 서버 정보 추가
  sprintf(buf, "%sConnections: close\r\n", buf);            // 연결 종료 정보 추가
  sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);  // 컨텐츠 길이 추가
  sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype); // 컨텐츠 타입 추가

  /* 응답 라인과 헤더를 클라이언트에게 보냄 */
  Rio_writen(fd, buf, strlen(buf)); 
  printf("Response headers: \n");
  printf("%s", buf);

  if (strcasecmp(method, "HEAD") == 0)
      return;

  /* 응답 바디 전송 */
  srcfd = Open(filename, O_RDONLY, 0);                       // 파일 열기
  //srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0); // 파일을 메모리에 동적할당

  /* Homework 11.9 */
  srcp = (char *) malloc(filesize); // mmap 대신 malloc 사용
  rio_readn(srcfd, srcp, filesize); // rio_readn 사용하기

  Close(srcfd);                                             // 파일 닫기
  Rio_writen(fd, srcp, filesize);                           // 클라이언트에게 파일 내용 전송
  // Munmap(srcp, filesize);                                // 메모리 할당 해제
  free(srcp);                                               // malloc 사용 => munmap에서 free로 변경  
}
  • tiny/tiny.c
    => HEAD 메서드에 대한 조건 추가
    => method 추가
/*
 * adder.c - a minimal CGI program that adds two numbers together
 */
/* $begin adder */
#include "csapp.h"

int main(void) {
    char *buf, *p, *method;
    char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
    int n1 = 0, n2 = 0;

    /* Extract the two arguments */
    /* 두 개의 인자 추출 */
    if ((buf = getenv("QUERY_STRING")) != NULL) {
        p = strchr(buf, '&');
        *p = '\0';
        strcpy(arg1, buf);
        strcpy(arg2, p + 1);
        n1 = atoi(arg1); // 첫 번째 인자를 정수로 변환
        n2 = atoi(arg2); // 두 번째 인자를 정수로 변환
    }

    /* Make the response body */
    /* 응답 본문 생성 */
    sprintf(content, "QUERY_STRING=%s", buf);
    sprintf(content, "Welcome to add.com: ");
    sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
    sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
            content, n1, n2, n1 + n2);
    sprintf(content, "%sThanks for visiting!\r\n", content);

    /* Generate the HTTP response */
    /* HTTP 응답 생성 */
    printf("Connection: close\r\n");
    printf("Content-length: %d\r\n", (int) strlen(content));
    printf("Content-type: text/html\r\n\r\n");
    printf("%s", content); // 생성된 응답 본문 출력
    fflush(stdout); // 출력 버퍼를 비워줌

    exit(0);
}
/* $end adder */
  • tiny/adder.c => char *buf, *p, *method; 메서드 추가

확인 방법

실행 후
telnet localhost 8000
HEAD / HTTP/1.1
Host: localhost
차례로 입력한다.

1. 실행


실행 후 터미널 분할로 확인하는것이 편리하다!

2. 로컬 컴퓨터의 8000번 포트로 텍스트 기반의 통신을 시도

telnet localhost 8000

3. HTTP 프로토콜의 요청 메시지

서버에게 리소스의 헤더 정보만을 요청
HEAD / HTTP/1.1

4. 요청이 전송되는 호스트를 명시

Host: localhost

profile
Sunny Day!

0개의 댓글