Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Last active February 27, 2026 13:25
Show Gist options
  • Select an option

  • Save masakielastic/524ec39492720a1daf2f8a36b6ca822f to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/524ec39492720a1daf2f8a36b6ca822f to your computer and use it in GitHub Desktop.
Rust で HTTP/1 の TCP サーバーとクライアントの例

Rust で HTTP/1 の TCP サーバーとクライアントの例

サーバー

src/main.rs

use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::time::Duration;

fn handle_client(mut stream: TcpStream) -> std::io::Result<()> {
    // 受信待ちで詰まらないように(適当に短め)
    stream.set_read_timeout(Some(Duration::from_secs(2)))?;

    // リクエストを軽く読み捨て(本格解析はしない)
    let mut buf = [0u8; 4096];
    let _ = stream.read(&mut buf); // タイムアウトでもOK(無視)

    let body = b"Hello from Rust TCP!\n";
    let header = format!(
        "HTTP/1.1 200 OK\r\n\
         Content-Type: text/plain; charset=utf-8\r\n\
         Content-Length: {}\r\n\
         Connection: close\r\n\
         \r\n",
        body.len()
    );

    stream.write_all(header.as_bytes())?;
    stream.write_all(body)?;
    stream.flush()?;
    Ok(())
}

fn main() -> std::io::Result<()> {
    let addr = "127.0.0.1:8080";
    let listener = TcpListener::bind(addr)?;
    eprintln!("listening on http://{addr}");

    for incoming in listener.incoming() {
        match incoming {
            Ok(stream) => {
                if let Err(e) = handle_client(stream) {
                    eprintln!("client error: {e}");
                }
            }
            Err(e) => eprintln!("accept error: {e}"),
        }
    }
    Ok(())
}

クライアント

use std::io::{Read, Write};
use std::net::TcpStream;

fn main() -> std::io::Result<()> {
    let host = "httpbin.org";
    let addr = format!("{host}:80");

    let mut stream = TcpStream::connect(addr)?;

    // HTTP/1.1 では Host ヘッダ必須
    let request = format!(
        "GET /get HTTP/1.1\r\n\
         Host: {host}\r\n\
         User-Agent: rust-tcp-client/0.1\r\n\
         Accept: */*\r\n\
         Connection: close\r\n\
         \r\n"
    );

    stream.write_all(request.as_bytes())?;

    let mut response = String::new();
    stream.read_to_string(&mut response)?;

    println!("{response}");

    Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment