本系列是關(guān)于用Rust構(gòu)建一個(gè)KV Server的系列文章,內(nèi)容包括用tokio做底層異步網(wǎng)絡(luò)通訊、使用toml文件做配置、protobuf做傳輸協(xié)議、內(nèi)存/RockDB做數(shù)據(jù)存儲(chǔ)、事件通知、優(yōu)雅關(guān)機(jī)、并發(fā)連接限制及測量監(jiān)控等。
讓我們先使用tokio實(shí)現(xiàn)一個(gè)簡單的Client & Server通訊模型,然后在此基礎(chǔ)上逐步實(shí)現(xiàn)上面提及的各項(xiàng)內(nèi)容。
創(chuàng)建一個(gè)新項(xiàng)目:
cargo new --lib kvserver_rust
在Cargo.toml文件中加入tokio依賴:
[dependencies]tokio = { version = "1.19", features = ["full"] }
Server
在src目錄下創(chuàng)建bin文件夾,然后創(chuàng)建kv_server.rs文件:
use anyhow::Result;use tokio::{io::{AsyncReadExt, AsyncWriteExt},net::TcpListener,};#[tokio::main]async fn main() -> Result<(), BoxError>> {let addr = "127.0.0.1:19999";let listener = TcpListener::bind(addr).await?;println!("Listening on {addr} ......");loop {let (mut stream, addr) = listener.accept().await?;println!("Client: {:?} connected", addr);tokio::spawn(async move {let mut buf = vec![0u8; 1024];loop {let n = stream.read(&mut buf).await.expect("從Socket讀取數(shù)據(jù)失??!");if n == 0 {return;}stream.write_all(&buf[0..n]).await.expect("向Socket寫入數(shù)據(jù)失??!");}});}}
在"127.0.0.1:19999"地址監(jiān)聽客戶端的連接,收到客戶端發(fā)來的信息后再返回給客戶端。
Client
在src/bin目錄下創(chuàng)建kv_client.rs文件:
use anyhow::Result;use tokio::{io::{AsyncReadExt, AsyncWriteExt},net::TcpStream,};#[tokio::main]async fn main() -> Result<(), Box>> {let addr = "127.0.0.1:19999";let mut stream = TcpStream::connect(addr).await?;let n = stream.write(b"Hello, world!").await?;println!("Send info successed!n = {n}");let mut buf = vec![0u8; 1024];let n = stream.read(&mut buf).await.expect("從Socket讀取數(shù)據(jù)失?。?);println!("Receive info:{}, n = {n}", String::from_utf8(buf).unwrap());Ok(())}
連接server端"127.0.0.1:19999"這個(gè)地址,向Server端發(fā)送"Hello, world!"消息,然后再接收Server端返回的消息。
打開兩個(gè)終端,分別執(zhí)行:
cargo run --bin kv_servercargo run --bin kv_client
執(zhí)行結(jié)果
kv_server:
Listening on 127.0.0.1:19999 ......Client: 127.0.0.1:51724 connected
kv_client:
Send info successed!n = 13Receive info:Hello, world!, n = 13
配置文件
使用 toml 做配置文件,serde 來處理配置的序列化和反序列化。在項(xiàng)目根目錄下新建conf目錄,并在下面新建server.conf文件:
[listen_address]addr = '127.0.0.1:19999'
和client.conf文件:
[connect_address]server_addr = '127.0.0.1:19999'
新建src/config.rs文件:
use std::{error::Error, fs};use serde::{Deserialize, Serialize};// Server端配置#[derive(Debug, Serialize, Deserialize)]pub struct ServerConfig {pub listen_address: ListenAddress,}// 監(jiān)聽地址#[derive(Debug, Serialize, Deserialize)]pub struct ListenAddress {pub addr: String,}// Client端配置#[derive(Debug, Serialize, Deserialize)]pub struct ClientConfig {pub connect_address: ConnectAddress,}// 連接地址#[derive(Debug, Serialize, Deserialize)]pub struct ConnectAddress {pub server_addr: String,}impl ServerConfig {// 加載Server端配置文件pub fn load(path: &str) -> Result<Self, Box> {let config = fs::read_to_string(path)?;let server_conf: Self = toml::from_str(&config)?;Ok(server_conf)}}impl ClientConfig {// 加載Client端配置文件pub fn load(path: &str) -> Result<Self, Box> {let config = fs::read_to_string(path)?;let client_conf: Self = toml::from_str(&config)?;Ok(client_conf)}}
然后在lib.rs中加入:
mod config;pub use config::*;
修改src/bin/kv_server.rs代碼:
#[tokio::main]async fn main() -> Result<(), Box> {let server_conf = ServerConfig::load("conf/server.conf")?;let listen_addr = server_conf.listen_address.addr;let listener = TcpListener::bind(&listen_addr).await?;println!("Listening on {} ......", listen_addr);......}
修改src/bin/kv_client.rs代碼:
#[tokio::main]async fn main() -> Result<(), BoxError>> {let client_conf = ClientConfig::load("conf/client.conf")?;let connect_addr = client_conf.connect_address.server_addr;let mut stream = TcpStream::connect(&connect_addr).await?;......}
運(yùn)行kv_sever和kv_client后,執(zhí)行結(jié)果與上面一致。
下一篇文章我們將使用Protobuf來實(shí)現(xiàn)客戶端與服務(wù)器之間的通信協(xié)議層。
完整代碼:
https://github.com/Justin02180218/kv_server_rust
-
Server
+關(guān)注
關(guān)注
0文章
95瀏覽量
25319 -
Client
+關(guān)注
關(guān)注
0文章
13瀏覽量
9319 -
Rust
+關(guān)注
關(guān)注
1文章
241瀏覽量
7643 -
Tokio
+關(guān)注
關(guān)注
0文章
12瀏覽量
274
原文標(biāo)題:[實(shí)戰(zhàn)分享] 用Rust實(shí)現(xiàn)KV Server-1 toml格式的配置文件
文章出處:【微信號(hào):Rust語言中文社區(qū),微信公眾號(hào):Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
如何在ESP8266上實(shí)現(xiàn)簡單的http-server和http-client?
如何實(shí)現(xiàn)Client/Server多個(gè)位置?
怎樣實(shí)現(xiàn)創(chuàng)建TCP Server后連接多個(gè)Client?
【HiSpark Wi-Fi IoT 智能家居套件試用】wifi連接并實(shí)現(xiàn)和上位機(jī)tcp client的通訊
Client Server模型數(shù)據(jù)實(shí)現(xiàn)技術(shù)
LabView TCP數(shù)據(jù)傳輸?shù)?個(gè)實(shí)例詳細(xì)資料概述
如何使用kubernetes client-go實(shí)踐一個(gè)簡單的與K8s交互過程
如何用Rust構(gòu)建一個(gè)KV Server系列
LabVIEW Actor Framwork:邊學(xué)邊做server和client
AT32講堂023 | AT32 MCU TCP client與TCP server如何與PC端通信
服務(wù)器Server和客戶端Client的區(qū)別
服務(wù)器Server和客戶端Client有哪些區(qū)別呢?
Tokio 模塊的優(yōu)雅停機(jī)機(jī)制
Tokio 的基本用法
Eureka Client的創(chuàng)建案例
使用tokio實(shí)現(xiàn)一個(gè)簡單的Client和Server通訊模型
評(píng)論