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 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)] #[derive(Debug)]
...@@ -15,35 +22,69 @@ pub enum Event { ...@@ -15,35 +22,69 @@ pub enum Event {
UpdateOnlineUsers, 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>) { pub async fn handle_events(mut receiver: mpsc::UnboundedReceiver<Event>) {
while let Some(event) = receiver.recv().await { while let Some(event) = receiver.recv().await {
match event { match event {
Event::NewConnection(from_id) => { Event::NewConnection(from_id) => {
println!("新连接: {}", from_id); println!("新连接: {}", from_id);
// 这里假设在其他地方有获取所有连接发送器的逻辑,暂时省略
// 实际应用中,需要实现向所有连接发送消息的功能
if let Err(e) = send_online_users_resp().await {
println!(
"在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}",
&from_id, e
);
}
} }
Event::CloseConnection(from_id) => { Event::CloseConnection(from_id) => {
println!("关闭连接: {}", from_id); println!("关闭连接: {}", from_id);
if let Err(e) = send_online_users_resp().await {
println!( // 移除客户端的发送者
"在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}", let mut senders = CLIENT_SENDERS.write().await;
&from_id, e senders.remove(&from_id);
);
}
} }
Event::UpdateOnlineUsers => { Event::UpdateOnlineUsers => {
// 这里可以实现其他触发更新在线用户列表的逻辑 // 这里可以实现其他触发更新在线用户列表的逻辑
// 为简单起见,暂未详细实现 // 为简单起见,暂未详细实现
println!("更新在线用户列表事件触发"); 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::online_users_update::send_online_users_resp;
use crate::handles::redis::remove_this_connection; use crate::handles::redis::remove_this_connection;
use crate::typing::used_typed::{ConnectionMap}; use tokio::sync::mpsc::UnboundedSender;
use tokio::sync::RwLockWriteGuard;
pub async fn handle_connection_error( pub async fn handle_connection_error(
from_id: &str, from_id: &str,
connections: &ConnectionMap, event_sender: &UnboundedSender<Event>,
) { ) {
println!("开始处理用户id: {} 的连接错误", from_id); 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: {},结果: {}", event_sender.send(Event::CloseConnection(from_id.to_string())).unwrap();
from_id, removed
);
// 从 Redis 中移除该用户的信息 // 从 Redis 中移除该用户的信息
if removed {
if let Err(e) = remove_this_connection(from_id).await { if let Err(e) = remove_this_connection(from_id).await {
println!("从 Redis 中移除用户信息时出错: {}", e); println!("从 Redis 中移除用户信息时出错: {}", e);
} }
}
// 准备更新用户链接 // 准备更新用户链接
if let Err(e) = send_online_users_resp().await { if let Err(e) = send_online_users_resp().await {
println!("在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}", &from_id,e); println!("在处理新用户id {} 之时广播,处理在线用户列表出错了:{:?}", from_id, e);
} else { } 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 crate::utils::json_utils::get_current_timestamp;
use futures::SinkExt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tungstenite::{Error, Message};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OnlineUserMessage { pub struct OnlineUserMessage {
...@@ -42,13 +40,14 @@ pub struct OnlineUsersMessage { ...@@ -42,13 +40,14 @@ pub struct OnlineUsersMessage {
pub time: u128, pub time: u128,
} }
pub async fn send_online_users_resp() -> Result<Vec<(String, String)>, serde_json::Error> {
pub async fn send_online_users_resp() -> Result<(), Error> {
let mut msg_data = Vec::new(); let mut msg_data = Vec::new();
let mut user_ids = Vec::new();
{ {
let online_users = ONLINE_USERS.read().await; let online_users = ONLINE_USERS.read().await;
println!("当前所有用户数据信息 ONLINE_USERS: {:?}", online_users); 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(); let parts: Vec<&str> = user_info_str.split(',').collect();
if parts.len() == 9 { if parts.len() == 9 {
let user_msg = OnlineUserMessage { let user_msg = OnlineUserMessage {
...@@ -63,14 +62,14 @@ pub async fn send_online_users_resp() -> Result<(), Error> { ...@@ -63,14 +62,14 @@ pub async fn send_online_users_resp() -> Result<(), Error> {
from_name: parts[8].to_string(), from_name: parts[8].to_string(),
}; };
msg_data.push(user_msg); msg_data.push(user_msg);
user_ids.push(user_id.clone());
} }
} }
} }
let mut connections = CONNECTIONS.write().await; let mut messages = Vec::new();
println!("当前的connections的keys是 {:?}", connections.keys()); for user_id in user_ids {
for (from_id, connection) in connections.iter_mut() { let to_id = user_id.clone();
let to_id = from_id.to_string();
let message = OnlineUsersMessage { let message = OnlineUsersMessage {
msg_type: "CmdUpdateOnlineUsers".to_string(), msg_type: "CmdUpdateOnlineUsers".to_string(),
from_id: "0".to_string(), from_id: "0".to_string(),
...@@ -80,16 +79,9 @@ pub async fn send_online_users_resp() -> Result<(), Error> { ...@@ -80,16 +79,9 @@ pub async fn send_online_users_resp() -> Result<(), Error> {
time: get_current_timestamp(), time: get_current_timestamp(),
}; };
let json_result = serde_json::to_string(&message); let json = serde_json::to_string(&message)?;
if let Err(e) = json_result { messages.push((user_id, json));
println!("序列化消息给用户 {} 失败: {}", from_id.to_string(), e);
continue;
} }
let json = json_result.unwrap();
if let Err(e) = connection.sender.send(Message::text(json)).await { Ok(messages)
println!("发送消息给用户 {} 失败: {}", from_id.to_string(), e);
}
}
Ok(())
} }
\ No newline at end of file
...@@ -21,6 +21,11 @@ async fn main() { ...@@ -21,6 +21,11 @@ async fn main() {
// 启动事件处理任务 // 启动事件处理任务
tokio::spawn(handle_events(event_receiver)); tokio::spawn(handle_events(event_receiver));
while let Ok((stream, _)) = listener.accept().await { 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 tokio_tungstenite::WebSocketStream;
use tungstenite::Message; use tungstenite::Message;
...@@ -11,6 +7,3 @@ pub struct Connection { ...@@ -11,6 +7,3 @@ pub struct Connection {
pub(crate) sender: futures::stream::SplitSink<WebSocketStream<tokio::net::TcpStream>, Message>, pub(crate) sender: futures::stream::SplitSink<WebSocketStream<tokio::net::TcpStream>, Message>,
pub(crate) receiver: futures::stream::SplitStream<WebSocketStream<tokio::net::TcpStream>>, pub(crate) receiver: futures::stream::SplitStream<WebSocketStream<tokio::net::TcpStream>>,
} }
\ No newline at end of file
pub type ConnectionMap = Arc<AsyncRwLock<HashMap<String, Connection>>>;
pub type TaskMap = Arc<RwLock<HashMap<String, JoinHandle<()>>>>;
\ 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