在這篇文章中,我們將在服務器端使用內存來存儲客戶端發送過來的數據。在實現數據存儲之前,我們先在客戶端使用Clap庫來解析命令行參數,并封裝成命令發送給服務器。
Clap解析命令行參數 在Cargo.toml文件中加入clap依賴:
clap = {version = "3.1", features = ["derive"]}在src目錄下新建args.rs文件,寫入以下代碼:
1useclap::Parser; 2 3#[derive(Debug,Parser)] 4#[clap(name="kv_client")] 5pubenumClientArgs{ 6Get{ 7#[clap(long)] 8key:String, 9}, 10Set{ 11#[clap(long)] 12key:String, 13#[clap(long)] 14value:String, 15}, 16Publish{ 17#[clap(long)] 18topic:String, 19#[clap(long)] 20value:String, 21}, 22Subscribe{ 23#[clap(long)] 24topic:String, 25}, 26Unsubscribe{ 27#[clap(long)] 28topic:String, 29#[clap(long)] 30id:u32, 31} 32}在src/lib.rs中加入以下代碼:
1modargs; 2pubuseargs::*;修改src/bin/kv_client.rs代碼:
1#[tokio::main] 2asyncfnmain()->Result<(),?Box>{ 3...... 4 5letclient_args=ClientArgs::parse(); 6 7//解析命令行參數,生成命令 8letcmd=process_args(client_args).await?; 9//命令編碼 10cmd.encode(&mutbuf).unwrap(); 11//發送命令 12stream.send(buf.freeze()).await.unwrap(); 13info!("Send command successed!"); 14 15loop{ 16tokio::select!{ 17Some(Ok(buf))=stream.next()=>{ 18letcmd_res=CmdResponse::decode(&buf[..]).unwrap(); 19info!("Receivearesponse:{:?}",cmd_res); 20} 21} 22} 23}
1//生成CmdRequest命令 2asyncfnprocess_args(client_args:ClientArgs)->Result>{ 3matchclient_args{ 4//生成GET命令 5ClientArgs::Get{key}=>{ 6Ok(CmdRequest::get(key)) 7}, 8//生成SET命令 9ClientArgs::Set{key,value}=>{ 10Ok(CmdRequest::set(key,value.into())) 11}, 12//生成PUBLISH命令 13ClientArgs::Publish{topic,value}=>{ 14Ok(CmdRequest::publish(topic,value.into())) 15}, 16//生成SUBSCRIBE命令 17ClientArgs::Subscribe{topic}=>{ 18Ok(CmdRequest::subscribe(topic)) 19}, 20//生成UNSUBSCRIBE命令 21ClientArgs::Unsubscribe{topic,id}=>{ 22Ok(CmdRequest::unsubscribe(topic,id)) 23} 24} 25}
打開一個終端,啟動kv_sever。打開另一個終端執行以下命令來測試客戶端:
RUST_LOG=info cargo run --bin kv_client get --key mykeyRUST_LOG=info cargo run --bin kv_client set --key mykey --value myvalue
服務器和客戶端都正常處理了收到的請求和響應。
內存存儲
我們使用dashmap crate在內存中存儲數據,dashmap是一個快速的并發map。
我們先創建src/storage目錄,再創建src/storage/mod.rs文件,然后在src/lib.rs文件中引入storage模塊。
在src/storage/mod.rs文件中定義一個storage trait,以便于以后不同存儲方式的擴展,代碼如下:
1usestd::Error; 2 3usebytes::Bytes; 4 5pubtraitStorage{ 6fnget(&self,key:&str)->Result
在src/storage目錄下創建mem_storage.rs文件:
1#[derive(Clone,Debug,Default)] 2pubstructMemStorage{ 3map:DashMap4} 5 6implMemStorage{ 7pubfnnew()->Self{ 8Self{ 9map:Default::default(), 10} 11} 12} 13 14implStorageforMemStorage{ 15fnget(&self,key:&str)->Result
修改kv_server.rs代碼:
1asyncfnmain()->Result<(),?Box>{ 2...... 3 4//初始化內存存儲 5letstorage=Arc::new(MemStorage::new()); 6 7loop{ 8...... 9 10letstor=storage.clone(); 11 12tokio::spawn(asyncmove{ 13//使用Frame的LengthDelimitedCodec進行編解碼操作 14letmutstream=Framed::new(stream,LengthDelimitedCodec::new()); 15whileletSome(Ok(mutbuf))=stream.next().await{ 16//對客戶端發來的protobuf請求命令進行拆包 17letcmd_req=CmdRequest::decode(&buf[..]).unwrap(); 18info!("Receiveacommand:{:?}",cmd_req); 19 20//處理請求命令 21letcmd_res=process_cmd(cmd_req,&stor).await.unwrap(); 22 23buf.clear(); 24 25//對protobuf的請求響應進行封包,然后發送給客戶端。 26cmd_res.encode(&mutbuf).unwrap(); 27stream.send(buf.freeze()).await.unwrap(); 28} 29info!("Client{:?}disconnected",addr); 30}); 31} 32} 33 34//處理請求命令,返回Response 35asyncfnprocess_cmd(req:CmdRequest,storage:&MemStorage)->Result >{ 36matchreq{ 37//處理GET命令 38CmdRequest{ 39req_data:Get(Get{key})), 40}=>{ 41letvalue=storage.get(&key)?; 42Ok(CmdResponse::new(200,"getsuccess".to_string(),value.unwrap_or_default())) 43}, 44//處理SET命令 45CmdRequest{ 46req_data:Set(Set{key,value})), 47}=>{ 48letvalue=storage.set(&key,value)?; 49Ok(CmdResponse::new(200,"setsuccess".to_string(),value.unwrap_or_default())) 50}, 51_=>Err("Invalidcommand".into()) 52} 53}
測試
1,打開一個終端,運行kv_server:
RUST_LOG=info cargo run --bin kv_server
2,打開一個終端,運行kv_client,執行set命令:
RUST_LOG=info cargo run --bin kv_client set --key mykey --value myvalue
3,打開一個終端,運行kv_client,執行get命令:
RUST_LOG=info cargo run --bin kv_client get --key mykey
執行結果:
INFO kv_client: Send command successed! INFO kv_client: Receive a response: CmdResponse { status: 200, message: "get success", value: b"myvalue" }
審核編輯:劉清
-
服務器
+關注
關注
12文章
9330瀏覽量
86131 -
數據存儲
+關注
關注
5文章
986瀏覽量
51106
原文標題:用Rust實現KV Server-3 命令行解析與內存存儲
文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
使用lwip socket udp功能,開發板為客戶端時不能夠接收服務器端發送過來的數據 ?
用隊列實現的1對N的TCP服務器端,自動回復信息總發錯客戶端
labview和 讀碼器的以太網通信 (沒有服務器端的程序)
LwIP調試問題,實現的是客戶端發過來的數據直接原樣返回
TCP:多個客戶端向服務器發送數據
為什么LWIP的TCP客戶端服務器端斷開后繼續發送數據就無法檢測到連接狀態?
使用Arduino編程和esp32的開發板,多個客戶端連接服務器時怎么判斷是哪個客戶端發送過來的數據?
如何使用esp8266在服務器和客戶端之間發送數據?
網絡調試和串口調試集合UDP TCP客戶端和TCP服務器端應用程序免費下載
![網絡調試和串口調試集合UDP TCP<b class='flag-5'>客戶端</b>和TCP<b class='flag-5'>服務器端</b>應用程序免費下載](https://file.elecfans.com/web1/M00/62/00/o4YBAFuHWwaANxpWAADMt7Js31c135.png)
評論