0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用tokio实现一个简单的Client和Server通讯模型

我快闭嘴 来源:coding到灯火阑珊 作者:李明 2022-09-09 09:45 次阅读

本系列是关于用Rust构建一个KV Server的系列文章,内容包括用tokio做底层异步网络通讯、使用toml文件做配置、protobuf做传输协议、内存/RockDB做数据存储、事件通知、优雅关机、并发连接限制及测量监控等。

让我们先使用tokio实现一个简单的Client & Server通讯模型,然后在此基础上逐步实现上面提及的各项内容。

创建一个新项目:

cargo new --lib kvserver_rust

在Cargo.toml文件中加入tokio依赖:

[dependencies]tokio = { version = "1.19", features = ["full"] }

Server

在src目录下创建bin文件夹,然后创建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读取数据失败!");
                if n == 0 {                    return;                }
                stream                    .write_all(&buf[0..n])                    .await                    .expect("向Socket写入数据失败!");            }        });    }}

在"127.0.0.1:19999"地址监听客户端的连接,收到客户端发来的信息后再返回给客户端。

Client

在src/bin目录下创建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读取数据失败!");    println!("Receive info:{}, n = {n}", String::from_utf8(buf).unwrap());
    Ok(())}

连接server端"127.0.0.1:19999"这个地址,向Server端发送"Hello, world!"消息,然后再接收Server端返回的消息。

打开两个终端,分别执行:

cargo run --bin kv_servercargo run --bin kv_client

执行结果

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 来处理配置的序列化和反序列化。在项目根目录下新建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,}
// 监听地址#[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?;    ......}

运行kv_sever和kv_client后,执行结果与上面一致。

下一篇文章我们将使用Protobuf来实现客户端与服务器之间的通信协议层。

完整代码:

https://github.com/Justin02180218/kv_server_rust



审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Server
    +关注

    关注

    0

    文章

    90

    浏览量

    23980
  • Client
    +关注

    关注

    0

    文章

    10

    浏览量

    8748
  • Rust
    +关注

    关注

    1

    文章

    228

    浏览量

    6542
  • Tokio
    +关注

    关注

    0

    文章

    12

    浏览量

    50

原文标题:[实战分享] 用Rust实现KV Server-1 toml格式的配置文件

文章出处:【微信号:Rust语言中文社区,微信公众号:Rust语言中文社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何在ESP8266上实现简单的http-server和http-client

    在 ESP8266 上实现简单的 http-server 和 http-client
    发表于 07-18 07:20

    如何实现Client/Server多个位置?

    考虑设置些东西来处理以上的远程建筑。例如,可能有三需要被分页的远程建筑。我可以在主楼和每个远程建筑的服务器上安装三客户。这是可行的
    发表于 04-30 06:42

    怎样实现创建TCP Server后连接多个Client

    版主你好,请问使用UCOS3+LWIP时,怎样实现创建TCP Server后,连接多个Client,然后能在每个Client之间进行不同数据格式的收发?比如我有2
    发表于 09-26 00:51

    【HiSpark Wi-Fi IoT 智能家居套件试用】wifi连接并实现和上位机tcp client通讯

    wifi成功之后,板子里面会有tcp的server监听6666端口的连接,并在连接上之后接受发送数据。需要在连接了同一个路由器的pc上,用python
    发表于 02-21 16:47

    Client Server模型数据实现技术

    本论文主要讨论基于Client/Server 数据完整性约束及其如何实施企业业务规则,并以SQLServer 和PowerBuilder 为例,介绍了数据完整性约束的实现技术。
    发表于 09-18 10:42 9次下载

    LabView TCP数据传输的7实例详细资料概述

    本文档的主要内容详细介绍的是LabView TCP数据传输的7实例资料概述包括了:TCP Client 单向通信,TCP Client 1 对多
    发表于 06-12 08:00 511次下载
    LabView TCP数据传输的7<b class='flag-5'>个</b>实例详细资料概述

    如何使用kubernetes client-go实践简单的与K8s交互过程

    【导读】Kubernetes项目使用Go语言编写,对Go api原生支持非常便捷。 本篇文章介绍了如何使用kubernetes client-go实践简单的与K8s交互过程
    的头像 发表于 02-02 11:16 6711次阅读
    如何使用kubernetes <b class='flag-5'>client</b>-go实践<b class='flag-5'>一</b><b class='flag-5'>个</b><b class='flag-5'>简单</b>的与K8s交互过程

    如何用Rust构建KV Server系列

    本系列是关于用Rust构建KV Server的系列文章,内容包括用tokio做底层异步网络通讯、使用toml文件做配置、protobuf
    的头像 发表于 09-14 10:03 1299次阅读

    LabVIEW Actor Framwork:边学边做serverclient

    现在要做一个类似聊天的demo,server端,若干个client端;首先是server启动
    的头像 发表于 06-01 15:49 1365次阅读
    LabVIEW Actor Framwork:边学边做<b class='flag-5'>server</b>和<b class='flag-5'>client</b>

    AT32讲堂023 | AT32 MCU TCP client与TCP server如何与PC端通信

    概述使用TCP执行通讯时,会有ServerClient的差别。Server是经由开启特定的Port来等待来自Client端的连线需求;而
    的头像 发表于 08-19 09:52 1143次阅读
    AT32讲堂023 | AT32 MCU TCP <b class='flag-5'>client</b>与TCP <b class='flag-5'>server</b>如何与PC端通信

    服务器Server和客户端Client的区别

    例如在使用TCP通讯建立连接时采用客户端服务器模式,这种模式又常常被称为主从式架构,简称为C/S结构,属于种网络通讯架构,将通讯的双方以客户端(C
    的头像 发表于 09-06 16:13 1297次阅读
    服务器<b class='flag-5'>Server</b>和客户端<b class='flag-5'>Client</b>的区别

    服务器Server和客户端Client有哪些区别呢?

    例如在使用TCP通讯建立连接时采用客户端服务器模式,这种模式又常常被称为主从式架构,简称为C/S结构,属于种网络通讯架构,将通讯的双方以客户端(C
    的头像 发表于 09-06 16:14 2319次阅读
    服务器<b class='flag-5'>Server</b>和客户端<b class='flag-5'>Client</b>有哪些区别呢?

    Tokio 模块的优雅停机机制

    在进行高并发、网络编程时,优雅停机是非常重要的问题。在 Rust 语言中,Tokio非常流行的异步编程框架,它提供了
    的头像 发表于 09-19 15:26 562次阅读

    Tokio 的基本用法

    Tokio异步 I/O 框架,它提供了种高效的方式来编写异步代码。它使用 Rust 语言的 Futures 库来管理异步任务,并使用 Reactor 模式来处理 I/O 事件
    的头像 发表于 09-19 16:05 755次阅读

    Eureka Client的创建案例

    在上篇中已经讲了 Eureka Server 的配置文件读取。接下来讲讲 Eureka Client 的创建。每一个 eureka server 都是
    的头像 发表于 10-09 17:03 473次阅读
    Eureka <b class='flag-5'>Client</b>的创建案例