色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用Protobuf實現客戶端與服務器之間的通信協議層

我快閉嘴 ? 來源:coding到燈火闌珊 ? 作者:李明 ? 2022-09-14 09:26 ? 次閱讀
本系列是關于用Rust構建一個KV Server的系列文章,內容包括用tokio做底層異步網絡通訊、使用toml文件做配置、protobuf做傳輸協議、內存/RockDB做數據存儲、事件通知、優雅關機、并發連接限制及測量監控等。
在上一篇文章中,我們用tokio實現了客戶端和服務器的基本框架并設置了toml格式的配置文件。在這一篇文章中,我們參考Redis的命令:GET、SET、PUBLISH和SUBSCRIBE,使用Protobuf來實現客戶端與服務器之間的通信協議層。為了處理Protobuf,我們加入了post庫。同時加入了tracing庫用于日志處理。Cargo.toml如下:
[dependencies]anyhow = "1"tokio = { version = "1.19", features = ["full"] }serde = { version = "1", features = ["derive"] }toml = "0.5"tracing = "0.1"tracing-subscriber = "0.3"bytes = "1"prost = "0.11"
[build-dependencies]prost-build = "0.11"
Protobuf在項目根目錄下新建cmd.proto,加入如下代碼:
 1syntax="proto3";
 2
 3packagecmd;
 4
 5//命令請求
 6messageCmdRequest{
 7oneofreq_data{
 8Getget=1;
 9Setset=2;
10Publishpublish=3;
11Subscribesubscribe=4;
12Unsubscribeunsubscribe=5;
13}
14}
15
16//服務器的響應
17messageCmdResponse{
18uint32status=1;
19stringmessage=2;
20bytesvalue=3;
21}
22
23//請求值命令
24messageGet{
25stringkey=1;
26}
27
28//存儲值命令
29messageSet{
30stringkey=1;
31bytesvalue=2;
32uint32expire=3;
33}
34
35//向Topic發布值命令
36messagePublish{
37stringtopic=1;
38bytesvalue=2;
39}
40
41//訂閱Topic命令
42messageSubscribe{
43stringtopic=1;
44}
45
46//取消訂閱命令
47messageUnsubscribe{
48stringtopic=1;
49uint32id=2;
50}
在src目錄下創建pb目錄,在根目錄下創建build.rs文件,加入如下代碼:
1fnmain(){
2letmutconf=prost_build::new();
3conf.bytes(&["."]);
4conf.type_attribute(".","#[derive(PartialOrd)]");
5conf.out_dir("src/pb")
6.compile_protos(&["cmd.proto"],&["."])
7.unwrap();
8}
在src/pb目錄下已經自動生成了cmd.rs文件。在src/pb目錄下創建mod.rs文件,加入如下代碼:
 1usebytes::Bytes;
 2
 3usecrate::{cmd_request::ReqData,CmdRequest,Get,Publish,Set,Subscribe,Unsubscribe};
 4
 5pubmodcmd;
 6
 7implCmdRequest{
 8//GET命令
 9pubfnget(key:implInto)->Self{
10Self{
11req_data:Some(ReqData::Get(Get{key:key.into()})),
12}
13}
14
15//SET命令
16pubfnset(key:implInto,value:Bytes,expire:u32)->Self{
17Self{
18req_data:Some(ReqData::Set(Set{
19key:key.into(),
20value,
21expire,
22})),
23}
24}
25
26//PUBLISH命令
27pubfnpublish(topic:implInto,value:Bytes)->Self{
28Self{
29req_data:Some(ReqData::Publish(Publish{
30topic:topic.into(),
31value,
32})),
33}
34}
35
36//訂閱命令
37pubfnsubscribe(topic:implInto)->Self{
38Self{
39req_data:Some(ReqData::Subscribe(Subscribe{
40topic:topic.into(),
41})),
42}
43}
44
45//解除訂閱命令
46pubfnunsubscribe(topic:implInto,id:u32)->Self{
47Self{
48req_data:Some(ReqData::Unsubscribe(Unsubscribe{
49topic:topic.into(),
50id,
51})),
52}
53}
54}
55
56implCmdResponse{
57pubfnnew(status:u32,message:String,value:Bytes)->Self{
58Self{
59status,
60message,
61value,
62}
63}
64}
在 src/lib.rs 中,引入pb模塊:
1modpb;
2pubusepb::*;
客戶端 & 服務器我們使用tokio-util庫的Frame里的LengthDelimitedCodec(根據長度進行編解碼)對protobuf協議進行封包解包。在Cargo.toml里加入tokio-util依賴:
[dependencies]......futures = "0.3"tokio-util = {version = "0.7", features = ["codec"]}......
修改src/bin/kv_server.rs代碼:
 1#[tokio::main]
 2asyncfnmain()->Result<(),Box>{
 3tracing_subscriber::init();
 4
 5......
 6
 7loop{
 8......
 9
10tokio::spawn(asyncmove{
11//使用Frame的LengthDelimitedCodec進行編解碼操作
12letmutstream=Framed::new(stream,LengthDelimitedCodec::new());
13whileletSome(Ok(mutbuf))=stream.next().await{
14//對客戶端發來的protobuf請求命令進行拆包
15letcmd_req=CmdRequest::decode(&buf[..]).unwrap();
16info!("Receiveacommand:{:?}",cmd_req);
17
18buf.clear();
19
20//對protobuf的請求響應進行封包,然后發送給客戶端。
21letcmd_res=CmdResponse::new(200,"success".to_string(),Bytes::default());
22cmd_res.encode(&mutbuf).unwrap();
23stream.send(buf.freeze()).await.unwrap();
24}
25info!("Client{:?}disconnected",addr);
26});
27}
28}
修改src/bin/kv_client.rs代碼:
 1#[tokio::main]
 2asyncfnmain()->Result<(),Box>{
 3tracing_subscriber::init();
 4
 5......
 6
 7//使用Frame的LengthDelimitedCodec進行編解碼操作
 8letmutstream=Framed::new(stream,LengthDelimitedCodec::new());
 9letmutbuf=BytesMut::new();
10
11//創建GET命令
12letcmd_get=CmdRequest::get("mykey");
13cmd_get.encode(&mutbuf).unwrap();
14
15//發送GET命令
16stream.send(buf.freeze()).await.unwrap();
17info!("Send info successed!");
18
19//接收服務器返回的響應
20whileletSome(Ok(buf))=stream.next().await{
21letcmd_res=CmdResponse::decode(&buf[..]).unwrap();
22info!("Receivearesponse:{:?}",cmd_res);
23}
24
25Ok(())
26}
我們打開二個終端,分別輸入以下命令:
RUST_LOG=info cargo run --bin kv_serverRUST_LOG=info cargo run --bin kv_client
服務器執行結果:
INFO kv_server: Listening on 127.0.0.1:19999 ......INFO kv_server: Client: 127.0.0.1:50655 connectedINFO kv_server: Receive a command: CmdRequest { req_data: Some(Get(Get { key: "mykey" })) }
客戶端執行結果:
INFO kv_client: Send info successedINFO kv_client: Receive a response: CmdResponse { status: 200, message: "success", value: b"" }

服務器和客戶端都正常處理了收到的請求和響應。 下一篇文章我們將在服務器端使用內存來存儲客戶端發送過來的數據。 完整代碼:https://github.com/Justin02180218/kv_server_rust


審核編輯:湯梓紅


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 通信協議
    +關注

    關注

    28

    文章

    887

    瀏覽量

    40317
  • 服務器
    +關注

    關注

    12

    文章

    9202

    瀏覽量

    85526
  • 客戶端
    +關注

    關注

    1

    文章

    290

    瀏覽量

    16700

原文標題:用Rust實現KV Server-2 協議層

文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    一個服務器,多個客戶端,怎么向指定的客戶端發數據

    我用labview做服務器,單片機做客戶端客戶端幾百個,怎么區分客戶端,給指定的客戶發發數據
    發表于 06-01 09:26

    如何實現服務器對指定客戶端的監聽?

    我現在能做出的是單服務器接收單客戶端的采集信息,想要實現RT所述,有沒有大佬指點一二!!!(最好是有源碼)
    發表于 05-29 16:17

    labview-TCP多客戶端服務器

    labview-TCP多客戶端服務器一個服務器上位機,多個下位機客戶端
    發表于 03-26 16:58

    怎么使用Paho來實現和MQTT服務器的基本通信

    MQTT協議的全稱叫“消息隊列遙測傳輸”協議。它是一個輕量級的通信協議。旨在為低帶寬、高延時、不穩定網絡中的物聯網設備提供消息傳輸服務。它運行在TCP/IP
    發表于 09-11 11:52

    BTC設備服務器的系統搭建

    ?:Node.js通信協議:HTTP、Socket3. Node.js 實現 Socket 通信________________________________________Socket 主要作?是
    發表于 09-24 09:05

    4412開發板Qt網絡編程-TCP實現服務器客戶端

    Protocol)是一種面向連接的,可靠的,基于字節流的傳輸通信協議,傳輸數據穩定可靠。在 help 索引中搜索到如圖 兩個重要類:服務器編程中兩個類都會用到,客戶端編程中只會用到
    發表于 04-28 15:33

    如何實現服務器客戶端數據交互?

    如何實現服務器客戶端數據交互?
    發表于 10-26 07:22

    當WiFi信號變低時,服務器客戶端之間的TCP通信丟失,如何使客戶端重新連接?

    大家好, 當 WiFi 信號變低時,服務器客戶端之間的 TCP 通信丟失,比如超過 -80dBm。一旦客戶端斷開連接,它就無法重新連接并正
    發表于 05-15 07:31

    服務器客戶端之間的TCP通信丟失怎么處理?

    嗨, 當 WiFi 信號變低時,比如超過 -80dBm,我面臨服務器客戶端之間的 TCP 通信丟失。一旦客戶端斷開連接,它就無法重新連接并
    發表于 05-16 08:19

    客戶端服務器和網絡技術

    基于服務器的計算代表著一種應用程序部署方法。 對以下基于服務器的計算環境而言,瘦客戶端是理想的客戶端設備: 借助 Windows 2000 或 Windows Server 2003
    發表于 07-02 16:46 ?17次下載
    瘦<b class='flag-5'>客戶端</b>的<b class='flag-5'>服務器</b>和網絡技術

    TCP通信服務器端客戶端同機互傳的簡單示例程序免費下載

    本文檔的主要內容詳細介紹的是TCP通信服務器端客戶端同機互傳的簡單示例程序免費下載初學者學習。本例子是本計算機labview程序之間通信,如果要想
    發表于 10-25 08:00 ?9次下載
    TCP<b class='flag-5'>通信服務器端</b>和<b class='flag-5'>客戶端</b>同機互傳的簡單示例程序免費下載

    Linux下TCP網絡編程-創建服務器客戶端

    這篇文章介紹在Linux下的socket編程,完成TCP服務器客戶端的創建,實現數據通信
    的頭像 發表于 08-14 09:26 ?2514次閱讀
    Linux下TCP網絡編程-創建<b class='flag-5'>服務器</b>與<b class='flag-5'>客戶端</b>

    MQTT中服務端客戶端

    MQTT 是一種基于客戶端-服務端架構(C/S)的消息傳輸協議,所以在 MQTT 協議通信中,有兩個最為重要的角色,它們便是
    的頭像 發表于 07-30 14:55 ?2674次閱讀

    服務端如何控制客戶端之間的信息通訊

    服務端如何通過“主題”來控制客戶端之間的信息通訊,看下圖實例: 在以上圖示中一共有三個 MQTT 客戶端,它們分別是開發板、手機和電腦。MQTT
    的頭像 發表于 07-30 15:10 ?821次閱讀
    <b class='flag-5'>服務端</b>如何控制<b class='flag-5'>客戶端</b><b class='flag-5'>之間</b>的信息通訊

    服務器Server和客戶端Client的區別

    例如在使用TCP通訊建立連接時采用客戶端服務器模式,這種模式又常常被稱為主從式架構,簡稱為C/S結構,屬于一種網絡通訊架構,將通訊的雙方以客戶端(Client )與服務器 (Serve
    的頭像 發表于 09-06 16:13 ?1399次閱讀
    <b class='flag-5'>服務器</b>Server和<b class='flag-5'>客戶端</b>Client的區別
    主站蜘蛛池模板: 2019精品国产品在线不卡| 国产熟妇无码一区二| 精品综合久久久久久8888| 一本色道久久88加勒比—综合| 久久久久久久伊人电影| 2021久久最新国产精品| 欧美最猛黑人AAAAA片| 国产精华av午夜在线观看| 久久一级片| 啊…嗯啊好深男男高h文| 神马影院午夜理论二| 国产自产第一区c国产| 中文字幕在线观看亚洲视频| 欧美激情视频在线观看一区二区三区| 成人在线高清不卡免费视频| 亚瑟天堂久久一区二区影院| lesbabes性欧美| 亚洲 自拍 欧洲 视频二区| 久久精品熟女亚洲AV国产| 办公室里呻吟的丰满老师电影| 亚洲AV无码久久流水呻蜜桃久色| 旧里番ovaの催○セイ活指导| 成人在线视频网站| 一级淫片bbbxxx| 青娱乐极品视觉盛宴国产视频| 国产亚洲精品黑人粗大精选| 正在播放久久| 手机免费毛片| 久久人妻少妇嫩草AV無碼| 高H内射NP古文| 2020亚洲国产在线播放在线| 双手绑在床头调教乳尖| 美女露出乳胸扒开尿口| 国产极品美女视频福利| 99re热精品视频国产免费| 性欧美video| 欧美成人无码A区在线观看免费| 国产精品久久免费视频 | 欧美の无码国产の无码影院| 国产日韩精品一区二区在线观看 | 国产日韩亚洲专区无码|