使用Rust开发即时聊天室(一)

腾讯注册元宇宙相关商标

据36氪消息,天眼查App显示,近日,腾讯科技(深圳)有限公司申请注册“王者元宇宙”“天美元宇宙”商标,国际分类含社会服务、通讯服务,当前商标状态均为申请中。今年以来“元宇宙”大火,其商标已被多家公司及自然人抢注,国际分类含网站服务、教育娱乐等,此类商标状态多…

本文使用rust+tokio开发一个即时聊天室,将使用到channel、websocket、stackless coroutine、select相关的知识

1 创建项目,命名为chatroom

updeMacBook-Pro:test aron$ cargo new chatroom
     Created binary (application) `chatroom` package

2 添加项目依赖

#在Cargo.toml添加如下内容
tokio = { version = "1.11.0", features = ["full"] }

#支持websocket协议
tokio-tungstenite = "0.15.0"
futures-util = "0.3.16"

#日志组件
log = "0.4.14"
simple_logger = "1.13.0"
# uuid,我们用于标识UserID
uuid = { version = "0.8.2", features = ["serde""v4"] }
  • tokio-tungstenite 支持websocket
  • log simple_logger 用于日志输出
  • uuid 用于UserID的生成

3 添加聊天室结构体

pub struct ChatRoom {
    user_map: HashMap<String, User>,
    event_rx_channel: UnboundedReceiver<SystemEvent>,
}

impl ChatRoom {
    # 创建聊天室
    pub fn new(event_rx_channel: UnboundedReceiver<SystemEvent>) -> Self {
        ChatRoom {
            user_map: HashMap::new(),
            event_rx_channel,
        }
    }
    
    # 添加新用户
    pub fn add_user(&mut self, user: User) {
        self.user_map.insert(user.id.clone(), user);
    }

    # 删除用户
    pub fn remove_user(&mut self, userId: String) {
        self.user_map.remove(&userId);
    }

    # 广播消息
    pub async fn broadcast(&mut self, message: Message) {
        
    }

    # 处理事件
    pub async fn on_event_process(mut self) {
        
    }

    pub async fn join_room(raw_stream: TcpStream, system_sender: UnboundedSender<SystemEvent>, addr: SocketAddr) -> Result<(), IoError> {
        
    }
}

  • 先将ChatRoom的接口全部写出来,分别是添加用户,删除用户,广播消息,处理各类事件
  • user_map 用于保存聊天室内的全部用户
  • ChatRoom结构中包含的UnboundedReceiver,一个channel的接收器,用于接收各类事件。

4 事件处理

我们基于事件机制,处理聊天室的各种事件,如下列举了一些事件

  • JoinEvent用户加入聊天室事件,ChatRoom接收到该事件后,会将用户添加进聊天室
  • ExitEvent用户离开聊天室事件,ChatRoom接收到该事件后,会将用户移出聊天室 ExitEvent
  • MessageEvent用户发送消息事件,用户接收到新消息时,会将消息发送给ChatRoom用户广播
  • BroadcastEvent聊天室广播消息事件,ChatRoom将某个用户的消息广播给聊天室的所有用户

基于channel技术,我们将Event在用户和聊天室之间双向传递,然后针对每种event类型做出相应的操作,比如添加用户、删除用户、广播消息

#[derive(Clone)]
pub enum SystemEvent {
    JoinEvent {
        id: String,
        user: User,
    },

    ExitEvent {
        id: String,
    },

    MessageEvent {
        id: String,
        message: Message,
    },

    CommandEvent {
        command: i32,
    },

    BroadcastEvent {
        message: Message,
    },
}

我们定义了一个enum类型的SytsemEvent结构,使用enum的好处是rust的enum非常强大,借助rust的match表达式,可以自动解析enum对应的事件的类型和属性,比如

match event {
    SystemEvent::JoinEvent { id, user } => {
        self.add_user(user);
    }
    SystemEvent::ExitEvent { id } => {}
    SystemEvent::MessageEvent { id, message } => {
        self.broadcast(message).await;
    }
    SystemEvent::CommandEvent { command } => {}
    _ => {}
}

5 tokio select技术

下面举例说明下select的用法


async fn a() {}

async fn b() {}

async fn c() {
  a().await;
  b().await;
}

async fn d() {
  select {
    a() => {}
    b() => {}
  }
}

async fn e() {
  loop {
    select {
      a() => {}
      b() => {}
    }
  }
}

  • 上面是一段伪代码,定义了a和b两个函数
  • c函数中,a和b是按照顺序执行的
  • d函数中,使用了select,表示在等待a和b任意一个执行完成
  • e函数中,循环等待a和b的完成状态

在实际的开发中,也会遇到这种场景,同时等待两种或多种事件发生,这是就可以使用select技术

总结

本次先介绍聊天室开发所用到的相关基础技术,了解这些技术之后,我们就可以开始编写相关的代码了,后面的文章会将今天了解的相关概念编程成代码。

数据:Riot Blockchain 8月共产出441枚BTC,较去年增长约451%

据雅虎财经消息,9月9日,纳斯达克上市矿企Riot Blockchain发布8月份生产和运营更新,包括其2021年8月未经审计的比特币产量和其矿工部署状态。据悉,2021年8月,Riot共产出了441枚BTC,较去年8月80枚BTC的产量增加了约451%。到8…

Click to rate this post!
[Total: 0 Average: 0]

人已赞赏
名家说小白百科每日优选

DAOrayaki|算法治理实验:DAO治理动态、韧性及崩溃

2021-9-9 21:39:17

DfinityRust开发名家说小白百科每日优选

【为DeFi赋能】—ICP集成比特币提案概述

2021-9-14 14:10:22

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索