90·实战项目高级

实战:Redis 客户端

实战:Redis 客户端

学习目标

  1. 理解 Redis 协议 (RESP)
  2. 实现基本命令解析
  3. 掌握 TCP 通信

核心实现

use tokio::net::TcpStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

struct RedisClient {
    stream: TcpStream,
}

impl RedisClient {
    async fn connect(addr: &str) -> Result<Self, std::io::Error> {
        let stream = TcpStream::connect(addr).await?;
        Ok(RedisClient { stream })
    }

    async fn send_command(&mut self, cmd: &str, args: &[&str]) -> Result<String, std::io::Error> {
        // RESP 协议格式
        let mut request = format!("*{}\r\n", args.len() + 1);
        request.push_str(&format!("${}\r\n{}\r\n", cmd.len(), cmd));
        for arg in args {
            request.push_str(&format!("${}\r\n{}\r\n", arg.len(), arg));
        }

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

        let mut buf = [0; 1024];
        let n = self.stream.read(&mut buf).await?;
        Ok(String::from_utf8_lossy(&buf[..n]).to_string())
    }

    async fn set(&mut self, key: &str, value: &str) -> Result<String, std::io::Error> {
        self.send_command("SET", &[key, value]).await
    }

    async fn get(&mut self, key: &str) -> Result<String, std::io::Error> {
        self.send_command("GET", &[key]).await
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = RedisClient::connect("127.0.0.1:6379").await?;

    let resp = client.set("hello", "world").await?;
    println!("SET: {}", resp);

    let resp = client.get("hello").await?;
    println!("GET: {}", resp);

    Ok(())
}

小结

技能应用
RESP 协议Redis 通信协议
TCPtokio 异步 TCP
字节处理协议解析

练习编辑器

rust
Loading...