마지막 프로젝트: 비동기 러스트로 동시성 웹 서버 만들기

이 장에선, 비동기 러스트로 러스트북의 싱글스레드 기반 웹 서버 만들기 를 수정하여 여러개의 요청을 동시에 수행할 수 있게 할 것입니다.

개요

이 강좌가 끝나면 아래 코드가 만들어 질 것입니다.

src/main.rs:

use std::fs;
use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;

fn main() {
    // localhost 7878 포트에서 수신되는 TCP 연결을 listen하기
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();

    // 영원히 블록하면서, 이 IP 주소로 들어오는 요청을 처리
    for stream in listener.incoming() {
        let stream = stream.unwrap();

        handle_connection(stream);
    }
}

fn handle_connection(mut stream: TcpStream) {
    // 처음 1024 바이트의 데이터를 스트림으로부터 읽어들임
    let mut buffer = [0; 1024];
    stream.read(&mut buffer).unwrap();

    let get = b"GET / HTTP/1.1\r\n";

    // 요청 안의 데이터에 따라 환영인사로 응답하거나 404 에러
    let (status_line, filename) = if buffer.starts_with(get) {
        ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
    } else {
        ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")
    };
    let contents = fs::read_to_string(filename).unwrap();

    // 다시 스트림에 응답을 씀
    // 클라이언트에게 응답이 전송될 수 있게 스트림을 플러시함
    let response = format!("{status_line}{contents}");
    stream.write_all(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

hello.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello!</title>
  </head>
  <body>
    <h1>Hello!</h1>
    <p>Hi from Rust</p>
  </body>
</html>

404.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello!</title>
  </head>
  <body>
    <h1>Oops!</h1>
    <p>Sorry, I don't know what you're asking for.</p>
  </body>
</html>

cargo run으로 서버를 실행시켜서 브라우저에서 127.0.0.1:7878에 접속했다면, 페리스의 친근한 인사말을 볼 수 있을 겁니다!