7 个版本

0.2.1 2023年7月21日
0.2.0 2020年6月29日
0.1.4 2018年3月26日
0.1.3 2016年11月13日

#5 in #环形

Download history 31/week @ 2024-04-22 28/week @ 2024-05-13 7/week @ 2024-05-27 7/week @ 2024-06-10 1/week @ 2024-06-17 1/week @ 2024-06-24 25/week @ 2024-07-01 29/week @ 2024-07-08 4/week @ 2024-07-15 7/week @ 2024-07-22 53/week @ 2024-07-29 14/week @ 2024-08-05

每月78次下载
2 crates 中使用

MIT 许可证

43KB
738

CircBuf

build status codecov crates.io docs.rs License

文档

字节可增长环形缓冲区的实现。`CircBuf` 结构体管理在堆上分配的字节缓冲区。当需要时,缓冲区可以增长,并可以返回其内部缓冲区的切片,这些切片可以用于正常的 IO(`read` 和 `write`)以及矢量 IO(`readv` 和 `writev`)。

支持 `bytes`

如果启用了 `bytes` 功能标志,则 `bytes` crate 将作为依赖项添加,并为 `CircBuf` 实现了 `Buf` 和 `BufMut` 特性。实现了可选的矢量读写函数,允许您使用 `CircBuf` 进行高效的矢量 IO 操作,例如与 `tokio` 库一起使用。例如,查看 read_bufwrite_buf 方法,当启用了 `bytes` 功能标志时,这些方法可以接受 `CircBuf`。

示例

以下是一个简单示例,其中服务器使用 `CircBuf` 从客户端读取消息。它使用 `vecio` crate 在套接字上调用 `readv`。消息由竖线 `|` 分隔,服务器返回它收到的每个消息的字节数。

extern crate vecio;
extern crate circbuf;

use std::thread;
use std::net::{TcpListener, TcpStream};
use std::io::Write;
use vecio::Rawv;
use circbuf::CircBuf;

fn handle_client(mut stream: TcpStream) {
    let mut buf = CircBuf::new();
    let mut num_messages = 0; // number of messages from the client
    let mut num_bytes = 0; // number of bytes read since last '|'

    loop {
        // grow the buffer if it is less than half full
        if buf.len() > buf.avail() {
            buf.grow().unwrap();
        }

        let n;
        {
            n = match stream.readv(&buf.get_avail()) {
                Ok(n) => {
                    if n == 0 {
                        // EOF
                        println!("client closed connection");
                        break;
                    }
                    n
                }
                Err(e) => panic!("got an error reading from a connection: {}", e),
            };
        }

        println!("read {} bytes from the client", n);

        // update write cursor
        buf.advance_write(n);

        // parse request from client for messages seperated by '|'
        loop {
            match buf.find_from_index(b'|', num_bytes) {
                Some(i) => {
                    let response = format!("Message {} contained {} bytes\n", num_messages, num_bytes + i - 1); // don't include '|' in number of bytes
                    match stream.write(&response.as_bytes()) {
                        Ok(n) => {
                            println!("wrote {} bytes to the client", n);

                            // update read cursor past '|' and reset num_bytes since last '|'
                            buf.advance_read(i + 1);
                            num_bytes = 0;
                            num_messages += 1;
                        }
                        Err(e) => panic!("got an error writing to connection: {}", e),
                    }
                }
                None => break,
            }
        }
    }
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:8888").unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                thread::spawn(move || handle_client(stream));
            }
            Err(e) => panic!("got an error accepting connection: {}", e),
        }
    }
}

依赖项

~44KB