Commit 13b576df by qlintonger xeno

尝试使用事件机制来实现多线程沟通+1

parent b6126d1e
use crate::handles::online_users_update::send_online_users_resp;
use crate::handles::online_users_update::{send_online_users_resp};
use crate::typing::used_typed::Connection;
use tokio::sync::mpsc;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use futures::SinkExt;
use lazy_static::lazy_static;
use tungstenite::{Error, Message};
// 假设的用户详细信息结构体
#[derive(Debug)]
......@@ -15,35 +22,69 @@ pub enum Event {
UpdateOnlineUsers,
}
// 定义事件中心发送给客户端的消息类型
#[derive(Debug)]
pub enum ClientMessage {
CmdUpdateOnlineUsers,
SendMessage(String),
}
lazy_static! {
// 存储每个客户端的发送者,用于事件中心向客户端发送消息
pub static ref CLIENT_SENDERS: Arc<RwLock<HashMap<String, mpsc::Sender<ClientMessage>>>> =
Arc::new(RwLock::new(HashMap::new()));
}
// 注册客户端的发送者
pub async fn register_client(_event_sender: mpsc::UnboundedSender<Event>, center_to_client_sender: mpsc::Sender<ClientMessage>) {
// 这里假设可以从某个地方获取到客户端的 from_id
let from_id = "dummy_id".to_string(); // 实际需要替换为真实的 from_id
let mut senders = CLIENT_SENDERS.write().await;
senders.insert(from_id, center_to_client_sender);
}
// 处理事件的任务
pub async fn handle_events(mut receiver: mpsc::UnboundedReceiver<Event>) {
while let Some(event) = receiver.recv().await {
match event {
Event::NewConnection(from_id) => {
println!("新连接: {}", from_id);
// 这里假设在其他地方有获取所有连接发送器的逻辑,暂时省略
// 实际应用中,需要实现向所有连接发送消息的功能
if let Err(e) = send_online_users_resp().await {
println!(
"在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}",
&from_id, e
);
}
}
Event::CloseConnection(from_id) => {
println!("关闭连接: {}", from_id);
if let Err(e) = send_online_users_resp().await {
println!(
"在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}",
&from_id, e
);
}
// 移除客户端的发送者
let mut senders = CLIENT_SENDERS.write().await;
senders.remove(&from_id);
}
Event::UpdateOnlineUsers => {
// 这里可以实现其他触发更新在线用户列表的逻辑
// 为简单起见,暂未详细实现
println!("更新在线用户列表事件触发");
}
}
}
}
// 向指定客户端发送消息
async fn send_message_to_client(from_id: &str, message: String) -> Result<(), Error> {
let senders = CLIENT_SENDERS.read().await;
if let Some(sender) = senders.get(from_id) {
if let Err(e) = sender.send(ClientMessage::SendMessage(message)).await {
return Err(Error::Io(std::io::Error::new(std::io::ErrorKind::Other, e)));
}
}
Ok(())
}
// 通知所有客户端线程发送 CmdUpdateOnlineUsers 消息
async fn notify_all_clients_to_update_online_users() {
let senders = CLIENT_SENDERS.read().await;
for (_, sender) in senders.iter() {
if let Err(e) = sender.send(ClientMessage::CmdUpdateOnlineUsers).await {
println!("通知客户端更新在线用户列表失败: {:?}", e);
}
}
}
\ No newline at end of file
use crate::events::Event;
use crate::handles::online_users_update::send_online_users_resp;
use crate::handles::redis::remove_this_connection;
use crate::typing::used_typed::{ConnectionMap};
use tokio::sync::RwLockWriteGuard;
use tokio::sync::mpsc::UnboundedSender;
pub async fn handle_connection_error(
from_id: &str,
connections: &ConnectionMap,
event_sender: &UnboundedSender<Event>,
) {
println!("开始处理用户id: {} 的连接错误", from_id);
// 从全局连接映射中移除该连接
let removed = {
let mut connections: RwLockWriteGuard<'_, _> = connections.write().await;
println!("清除之前的keys {:?}", connections.keys());
let result = connections.remove(from_id).is_some();
println!("清除之后的keys {:?}", connections.keys());
result
};
println!(
"是否成功从全局连接映射中移除用户id: {},结果: {}",
from_id, removed
);
// 发送关闭连接事件
event_sender.send(Event::CloseConnection(from_id.to_string())).unwrap();
// 从 Redis 中移除该用户的信息
if removed {
if let Err(e) = remove_this_connection(from_id).await {
println!("从 Redis 中移除用户信息时出错: {}", e);
}
if let Err(e) = remove_this_connection(from_id).await {
println!("从 Redis 中移除用户信息时出错: {}", e);
}
// 准备更新用户链接
if let Err(e) = send_online_users_resp().await {
println!("在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}", &from_id,e);
println!("在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}", from_id, e);
} else {
println!("成功将用户id {} 退出广播至其余用户", &from_id);
println!("成功将用户id {} 退出广播至其余用户", from_id);
}
}
\ No newline at end of file
use crate::client::{CONNECTIONS, ONLINE_USERS};
use crate::client::ONLINE_USERS;
use crate::utils::json_utils::get_current_timestamp;
use futures::SinkExt;
use serde::{Deserialize, Serialize};
use tungstenite::{Error, Message};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OnlineUserMessage {
......@@ -42,13 +40,14 @@ pub struct OnlineUsersMessage {
pub time: u128,
}
pub async fn send_online_users_resp() -> Result<(), Error> {
pub async fn send_online_users_resp() -> Result<Vec<(String, String)>, serde_json::Error> {
let mut msg_data = Vec::new();
let mut user_ids = Vec::new();
{
let online_users = ONLINE_USERS.read().await;
println!("当前所有用户数据信息 ONLINE_USERS: {:?}", online_users);
for (_, user_info_str) in online_users.iter() {
for (user_id, user_info_str) in online_users.iter() {
let parts: Vec<&str> = user_info_str.split(',').collect();
if parts.len() == 9 {
let user_msg = OnlineUserMessage {
......@@ -63,14 +62,14 @@ pub async fn send_online_users_resp() -> Result<(), Error> {
from_name: parts[8].to_string(),
};
msg_data.push(user_msg);
user_ids.push(user_id.clone());
}
}
}
let mut connections = CONNECTIONS.write().await;
println!("当前的connections的keys是 {:?}", connections.keys());
for (from_id, connection) in connections.iter_mut() {
let to_id = from_id.to_string();
let mut messages = Vec::new();
for user_id in user_ids {
let to_id = user_id.clone();
let message = OnlineUsersMessage {
msg_type: "CmdUpdateOnlineUsers".to_string(),
from_id: "0".to_string(),
......@@ -80,16 +79,9 @@ pub async fn send_online_users_resp() -> Result<(), Error> {
time: get_current_timestamp(),
};
let json_result = serde_json::to_string(&message);
if let Err(e) = json_result {
println!("序列化消息给用户 {} 失败: {}", from_id.to_string(), e);
continue;
}
let json = json_result.unwrap();
if let Err(e) = connection.sender.send(Message::text(json)).await {
println!("发送消息给用户 {} 失败: {}", from_id.to_string(), e);
}
let json = serde_json::to_string(&message)?;
messages.push((user_id, json));
}
Ok(())
}
Ok(messages)
}
\ No newline at end of file
......@@ -21,6 +21,11 @@ async fn main() {
// 启动事件处理任务
tokio::spawn(handle_events(event_receiver));
while let Ok((stream, _)) = listener.accept().await {
tokio::spawn(handle_client(stream, event_sender.clone()));
let client_event_sender = event_sender.clone();
// 创建一个用于事件中心向客户端发送消息的通道
let (center_to_client_sender, center_to_client_receiver) = mpsc::channel(10);
tokio::spawn(handle_client(stream, &client_event_sender, center_to_client_receiver));
// 将客户端的发送者存储到事件中心,以便事件中心可以向客户端发送消息
events::register_client(client_event_sender, center_to_client_sender).await;
}
}
\ No newline at end of file
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use tokio::sync::RwLock as AsyncRwLock;
use tokio::task::JoinHandle;
use tokio_tungstenite::WebSocketStream;
use tungstenite::Message;
......@@ -10,7 +6,4 @@ use tungstenite::Message;
pub struct Connection {
pub(crate) sender: futures::stream::SplitSink<WebSocketStream<tokio::net::TcpStream>, Message>,
pub(crate) receiver: futures::stream::SplitStream<WebSocketStream<tokio::net::TcpStream>>,
}
pub type ConnectionMap = Arc<AsyncRwLock<HashMap<String, Connection>>>;
pub type TaskMap = Arc<RwLock<HashMap<String, JoinHandle<()>>>>;
\ No newline at end of file
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment