RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用tokio實(shí)現(xiàn)一個(gè)簡單的Client和Server通訊模型

我快閉嘴 ? 來源:coding到燈火闌珊 ? 作者:李明 ? 2022-09-09 09:45 ? 次閱讀

本系列是關(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



審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Server
    +關(guān)注

    關(guān)注

    0

    文章

    90

    瀏覽量

    24025
  • Client
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    8768
  • Rust
    +關(guān)注

    關(guān)注

    1

    文章

    228

    瀏覽量

    6601
  • Tokio
    +關(guān)注

    關(guān)注

    0

    文章

    12

    瀏覽量

    57

原文標(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)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何在ESP8266上實(shí)現(xiàn)簡單的http-server和http-client?

    在 ESP8266 上實(shí)現(xiàn)簡單的 http-server 和 http-client
    發(fā)表于 07-18 07:20

    如何實(shí)現(xiàn)Client/Server多個(gè)位置?

    考慮設(shè)置些東西來處理個(gè)以上的遠(yuǎn)程建筑。例如,可能有三個(gè)需要被分頁的遠(yuǎn)程建筑。我可以在主樓和每個(gè)遠(yuǎn)程建筑的服務(wù)器上安裝三個(gè)客戶。這是可行的
    發(fā)表于 04-30 06:42

    怎樣實(shí)現(xiàn)創(chuàng)建TCP Server后連接多個(gè)Client?

    版主你好,請(qǐng)問使用UCOS3+LWIP時(shí),怎樣實(shí)現(xiàn)創(chuàng)建TCP Server后,連接多個(gè)Client,然后能在每個(gè)Client之間進(jìn)行不同數(shù)據(jù)格式的收發(fā)?比如我有2
    發(fā)表于 09-26 00:51

    【HiSpark Wi-Fi IoT 智能家居套件試用】wifi連接并實(shí)現(xiàn)和上位機(jī)tcp client通訊

    wifi成功之后,板子里面會(huì)有個(gè)tcp的server監(jiān)聽6666端口的連接,并在連接上之后接受發(fā)送數(shù)據(jù)。需要在連接了同一個(gè)路由器的pc上,用python
    發(fā)表于 02-21 16:47

    Client Server模型數(shù)據(jù)實(shí)現(xiàn)技術(shù)

    本論文主要討論基于Client/Server 數(shù)據(jù)完整性約束及其如何實(shí)施企業(yè)業(yè)務(wù)規(guī)則,并以SQLServer 和PowerBuilder 為例,介紹了數(shù)據(jù)完整性約束的實(shí)現(xiàn)技術(shù)。
    發(fā)表于 09-18 10:42 ?9次下載

    LabView TCP數(shù)據(jù)傳輸?shù)?個(gè)實(shí)例詳細(xì)資料概述

    本文檔的主要內(nèi)容詳細(xì)介紹的是LabView TCP數(shù)據(jù)傳輸?shù)?個(gè)實(shí)例資料概述包括了:TCP Client 單向通信,TCP Client 1 對(duì)多
    發(fā)表于 06-12 08:00 ?513次下載
    LabView TCP數(shù)據(jù)傳輸?shù)?<b class='flag-5'>個(gè)</b>實(shí)例詳細(xì)資料概述

    如何使用kubernetes client-go實(shí)踐個(gè)簡單的與K8s交互過程

    【導(dǎo)讀】Kubernetes項(xiàng)目使用Go語言編寫,對(duì)Go api原生支持非常便捷。 本篇文章介紹了如何使用kubernetes client-go實(shí)踐個(gè)簡單的與K8s交互過程
    的頭像 發(fā)表于 02-02 11:16 ?6843次閱讀
    如何使用kubernetes <b class='flag-5'>client</b>-go實(shí)踐<b class='flag-5'>一</b><b class='flag-5'>個(gè)</b><b class='flag-5'>簡單</b>的與K8s交互過程

    如何用Rust構(gòu)建個(gè)KV Server系列

    本系列是關(guān)于用Rust構(gòu)建個(gè)KV Server的系列文章,內(nèi)容包括用tokio做底層異步網(wǎng)絡(luò)通訊、使用toml文件做配置、protobuf
    的頭像 發(fā)表于 09-14 10:03 ?1325次閱讀

    LabVIEW Actor Framwork:邊學(xué)邊做serverclient

    現(xiàn)在要做一個(gè)類似聊天的demo,個(gè)server端,若干個(gè)client端;首先是server啟動(dòng)
    的頭像 發(fā)表于 06-01 15:49 ?1426次閱讀
    LabVIEW Actor Framwork:邊學(xué)邊做<b class='flag-5'>server</b>和<b class='flag-5'>client</b>

    AT32講堂023 | AT32 MCU TCP client與TCP server如何與PC端通信

    概述使用TCP執(zhí)行通訊時(shí),會(huì)有ServerClient的差別。Server是經(jīng)由開啟特定的Port來等待來自Client端的連線需求;而
    的頭像 發(fā)表于 08-19 09:52 ?1208次閱讀
    AT32講堂023 | AT32 MCU TCP <b class='flag-5'>client</b>與TCP <b class='flag-5'>server</b>如何與PC端通信

    服務(wù)器Server和客戶端Client的區(qū)別

    例如在使用TCP通訊建立連接時(shí)采用客戶端服務(wù)器模式,這種模式又常常被稱為主從式架構(gòu),簡稱為C/S結(jié)構(gòu),屬于種網(wǎng)絡(luò)通訊架構(gòu),將通訊的雙方以客戶端(C
    的頭像 發(fā)表于 09-06 16:13 ?1367次閱讀
    服務(wù)器<b class='flag-5'>Server</b>和客戶端<b class='flag-5'>Client</b>的區(qū)別

    服務(wù)器Server和客戶端Client有哪些區(qū)別呢?

    例如在使用TCP通訊建立連接時(shí)采用客戶端服務(wù)器模式,這種模式又常常被稱為主從式架構(gòu),簡稱為C/S結(jié)構(gòu),屬于種網(wǎng)絡(luò)通訊架構(gòu),將通訊的雙方以客戶端(C
    的頭像 發(fā)表于 09-06 16:14 ?2460次閱讀
    服務(wù)器<b class='flag-5'>Server</b>和客戶端<b class='flag-5'>Client</b>有哪些區(qū)別呢?

    Tokio 模塊的優(yōu)雅停機(jī)機(jī)制

    在進(jìn)行高并發(fā)、網(wǎng)絡(luò)編程時(shí),優(yōu)雅停機(jī)是個(gè)非常重要的問題。在 Rust 語言中,Tokio個(gè)非常流行的異步編程框架,它提供了
    的頭像 發(fā)表于 09-19 15:26 ?632次閱讀

    Tokio 的基本用法

    Tokio個(gè)異步 I/O 框架,它提供了種高效的方式來編寫異步代碼。它使用 Rust 語言的 Futures 庫來管理異步任務(wù),并使用 Reactor 模式來處理 I/O 事件
    的頭像 發(fā)表于 09-19 16:05 ?817次閱讀

    Eureka Client的創(chuàng)建案例

    在上篇中已經(jīng)講了 Eureka Server 的配置文件讀取。接下來講講 Eureka Client 的創(chuàng)建。每一個(gè) eureka server 都是
    的頭像 發(fā)表于 10-09 17:03 ?507次閱讀
    Eureka <b class='flag-5'>Client</b>的創(chuàng)建案例
    RM新时代网站-首页