惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
月光博客
月光博客
The GitHub Blog
The GitHub Blog
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
T
Tailwind CSS Blog
美团技术团队
D
Docker
V
Visual Studio Blog
Martin Fowler
Martin Fowler
博客园 - 聂微东
The Cloudflare Blog

The Rust Programming Language Forum - Latest topics

Beginner building a Rust backend framework (AI-assisted) — feedback appreciated C++ to Rust -- Exceptions Re-exporting a trait with a custom derive_macro Gold linker is deprecated Why is using PhantomData valid in this case? Code review for Static Pool Allocator Looking for a pool based allocator Why is this legal? What does it mean for Rustc to run "out of TLS keys"? Using async/await internally with no internal runtime, but exposing a nonblocking poll API — is this a reasonable design? Testing functions that use randomness `cargo-path`: improve coding agents&#39; ability to find Rust documentation Rust task runners Lifetime weird case Windows - USB device not detected A random rustc-ice-[...].txt file appeared Develop rust where the environment is setup in a docker Undefined Behavior: in-bounds pointer arithmetic failed: attempting to offset pointer by 20 bytes, but got alloc238 which is only 1 byte from the end of the allocation Unbug 0.5 - Runtime debug assertions Is there a tiny error in section 6.2 Reference types? Lifetime woes implementing ratatui::Widget for a reference Rusqlite + Chrono: How do I simplify code to obtain chrono datetime value From OOP to Rust – struggling with code organization and data structure design Way to avoid a self-referential struct Rust RF and audio resources/communities Whyhttp - HTTP mocks that fail where the bug actually is Using tokio channel permits in a tower service Arc::increment_strong_count design question (cross-post) `&T`, `&mut T`, `Pin<&mut T>` and `&Cell<T>`: Ways of Borrowing a `T` Ratatui detect arrow key press and release
Quiche client sent message not received at the server side
Jason1 · 2026-04-21 · via The Rust Programming Language Forum - Latest topics

I want to use quiche crate as message passing without its http layer. So I attempted to create a minimum working example by borrowing from its client.rs and server.rs. However, it is complicated that mixes up with mio event system that I am not familiar with. Thus I refactor by combining the quiche's example code plus the code produced by google, and the code is listed as below. I understand it is rubbish, but at least I have a start point.

The problem I encountered is the code gets complied, but the message sent from the client side looks like not received at the server side. The client merely prints Error:Done, which looks like no more data to process. I suppose my problem:

  1. What is the correct steps to perform handshake?
  2. What is the follow up steps (recv, send, and so on) until connection.is_established()?
  3. What steps to close to connection?

Thanks.

Env
Rust version: rustc 1.92.0 (ded5c06cf 2025-12-08)

Cargo.toml

[package]
name = "hello-world"
version = "0.1.0"
edition = "2024"

[dependencies]
quiche = "0.28.0"


[[bin]]
name = "client"
path = "src/bin/client.rs"

[[bin]]
name = "server"
path = "src/bin/server.rs"

src/bin/client.rs


fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
    config.set_application_protos(&[b"echo"])?; // Custom ALPN
    config.set_max_idle_timeout(5000);

    let socket = UdpSocket::bind("127.0.0.1:0")?;
    let server_addr = "127.0.0.1:4433".parse()?;

    let scid = quiche::ConnectionId::from_vec(vec![0x1; 16]);
    let mut conn = quiche::connect(
        Some("localhost"),
        &scid,
        socket.local_addr()?,
        server_addr,
        &mut config,
    )?;

    let mut out = [0; 1350];
    let (write, send_info) = conn.send(&mut out)?;
    socket.send_to(&out[..write], send_info.to)?;

    let mut buf = [0; 65535];
    loop {
        match socket.recv_from(&mut buf) {
            Ok((read, from)) => {
                   let recv_info = quiche::RecvInfo {
                        from,
                        to: socket.local_addr()?,
                    };
                    conn.recv(&mut buf[..read], recv_info)?;
            },
            Err(_) => break,
        }

        if conn.is_established() {
            conn.stream_send(0, b"hello message!", true)?;
            //break;
        }

        loop {
            let (write, send_info) = match conn.send(&mut out) {
                Ok(v) => v,
                Err(quiche::Error::Done) => break,
                Err(e) => return Err(e.into()),
            };
            socket.send_to(&out[..write], send_info.to)?;
        }
    }

    Ok(())
}

src/bin/server.rs

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut buf = [0; 65535];
    let mut out = [0; 65535];

    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
    config.set_application_protos(&[b"echo"])?; // custom protocol
    config.set_initial_max_data(10_000_000);
    config.set_initial_max_stream_data_bidi_local(1_000_000);
    config.set_initial_max_streams_bidi(100);
    config.load_cert_chain_from_pem_file("cert.pem")?;
    config.load_priv_key_from_pem_file("key.pem")?;

    let socket = UdpSocket::bind("127.0.0.1:4433")?;
    let mut conn: Option<quiche::Connection> = None;

    loop {
        let (read, from) = socket.recv_from(&mut buf)?;
        let scid = quiche::ConnectionId::from_ref(&[0xba, 0xad, 0xbe, 0xef]);
        if conn.is_none() {
            conn = Some(quiche::accept(
                &scid,
                None,
                socket.local_addr()?,
                from,
                &mut config,
            )?);
        }

        if let Some(ref mut connection) = conn {
            let recv_info = quiche::RecvInfo {
                from,
                to: socket.local_addr()?,
            };
            connection.recv(&mut buf[..read], recv_info)?;

            if connection.is_established() {
                for stream_id in connection.readable() {
                    let (read, _fin) = connection.stream_recv(stream_id, &mut buf)?;
                    // Echo back data
                    connection.stream_send(stream_id, &buf[..read], true)?;
                }
            }

            loop {
                let (write, _send_info) = match connection.send(&mut out) {
                    Ok(v) => v,
                    Err(quiche::Error::Done) => break,
                    Err(e) => {
                        return Err(e.into());
                    }
                };
                socket.send_to(&out[..write], from)?;
            }
        }

    }
}