Commit 5742ebd6 by qlintonger xeno

尝试多线程处理

parent 6dbb4cda
...@@ -13,3 +13,4 @@ futures = "0.3.31" ...@@ -13,3 +13,4 @@ futures = "0.3.31"
redis = "0.28.2" redis = "0.28.2"
redis_pool = "0.7.0" redis_pool = "0.7.0"
lazy_static = "1.4" lazy_static = "1.4"
dashmap = "4.0.0"
\ No newline at end of file
use std::sync::{Arc};
use std::time::Instant;
use futures::SinkExt;
use crate::events::Event;
use futures::stream::SplitSink;
use tokio::net::TcpStream;
use tokio::sync::mpsc::UnboundedSender;
use tokio::sync::Mutex;
use tokio_tungstenite::WebSocketStream;
use tungstenite::Message;
use crate::handles::handle_messages::handle_other_message;
use crate::handles::heartbeat::{heart_resp};
use crate::handles::online_users_update::send_online_users_and_send;
use crate::utils::json_utils::parse_message;
pub async fn handle_ws_msg(
msg: Message,
sender: Arc<Mutex<SplitSink<WebSocketStream<TcpStream>, Message>>>,
from_id: String,
event_sender: UnboundedSender<Event>,
last_heartbeat_time: Arc<Mutex<Instant>>,
) {
if msg.is_text() {
let text = msg.to_text().unwrap();
match parse_message(text) {
Ok(data) => {
match data.msg_type.as_str() {
"Heart" => {
println!("收到客户端心跳消息 {:?}", &data);
*last_heartbeat_time.lock().await = Instant::now();
if let Ok(json_str) = heart_resp(&from_id) {
let mut sender = sender.lock().await;
if let Err(e) = sender.send(Message::text(json_str)).await {
println!("发送心跳信息失败: {}", e);
// 发送关闭连接事件
event_sender.send(Event::CloseConnection(from_id.clone())).unwrap();
}
}
},
"GetOnlineUserList" => {
println!("收到客户端获取在线用户列表 {:?}", &data);
let mut sender = sender.lock().await;
if let Err(e) = send_online_users_and_send(&mut *sender, &from_id).await {
println!("处理在线用户列表出错了:{:?}", e);
// 发送关闭连接事件
event_sender.send(Event::CloseConnection(from_id.clone())).unwrap();
}
},
_ => {
let mut sender = sender.lock().await;
if let Err(e) = handle_other_message(&mut *sender, &data, &from_id).await {
println!("Failed to handle other message: {}", e);
// 发送关闭连接事件
event_sender.send(Event::CloseConnection(from_id.clone())).unwrap();
}
}
}
}
Err(e) => {
println!("解析JSON数据出错: {}", e);
}
}
}
}
\ No newline at end of file
use crate::handles::redis::{insert_this_connection, remove_this_connection};
use dashmap::DashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::sync::RwLock;
// 定义事件类型 // 定义事件类型
#[derive(Debug)] #[derive(Debug)]
pub enum Event { pub enum Event {
NewConnection(String), NewConnection(String, HashMap<String, String>),
CloseConnection(String), CloseConnection(String),
UpdateOnlineUsers,
} }
// 定义事件中心发送给客户端的消息类型 // 定义事件中心发送给客户端的消息类型
#[derive(Debug)] #[derive(Debug)]
pub enum ClientMessage { pub enum ClientMessage {
CmdUpdateOnlineUsers, CmdUpdateOnlineUsers,
SendMessage(String),
} }
lazy_static! { lazy_static! {
// 存储每个客户端的发送者,用于事件中心向客户端发送消息 // 存储每个客户端的发送者,用于事件中心向客户端发送消息
pub static ref CLIENT_SENDERS: Arc<RwLock<HashMap<String, mpsc::Sender<ClientMessage>>>> = pub static ref CLIENT_SENDERS: DashMap<String, mpsc::Sender<ClientMessage>> = DashMap::new();
Arc::new(RwLock::new(HashMap::new()));
} }
// 注册客户端的发送者 // 注册客户端的发送者
...@@ -30,39 +27,55 @@ pub async fn register_client( ...@@ -30,39 +27,55 @@ pub async fn register_client(
from_id: String, from_id: String,
center_to_client_sender: mpsc::Sender<ClientMessage>, center_to_client_sender: mpsc::Sender<ClientMessage>,
) { ) {
let mut senders = CLIENT_SENDERS.write().await; close_existing_connection(&from_id).await;
println!("注册客户端的发送者数量---》注册前: {:?}", &senders.len()); println!("注册用户 {} 前数量 {}", &from_id, CLIENT_SENDERS.len());
senders.insert(from_id, center_to_client_sender); CLIENT_SENDERS.insert(from_id.clone(), center_to_client_sender);
println!("注册客户端的发送者数量---》注册后: {:?}", &senders.len()); println!(
"注册用户 {} 后数量 {}",
from_id.clone(),
CLIENT_SENDERS.len()
);
}
// 关闭之前绑定的 WebSocket 连接
pub async fn close_existing_connection(from_id: &str) {
CLIENT_SENDERS.remove(from_id);
if let Err(e) = remove_this_connection(from_id).await {
println!("从 Redis 中移除用户信息时出错: {}", e);
}
} }
// 处理事件的任务 // 处理事件的任务
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, params) => {
println!("有新的连接 用户id {} 更新在线用户列表事件触发", from_id); println!("有新的连接 用户id {} 更新在线用户列表事件触发", from_id);
// 将该用户的信息插入到 Redis 中
if let Err(e) = insert_this_connection(&from_id, &params).await {
println!("将用户信息插入到 Redis 中时出错: {}", e);
}
notify_all_clients_to_update_online_users().await; notify_all_clients_to_update_online_users().await;
} }
Event::CloseConnection(from_id) => { Event::CloseConnection(from_id) => {
println!("有关闭的连接 用户id {} 更新在线用户列表事件触发", from_id); println!("有关闭的连接 用户id {} 更新在线用户列表事件触发", from_id);
close_existing_connection(&from_id).await;
notify_all_clients_to_update_online_users().await; notify_all_clients_to_update_online_users().await;
} }
Event::UpdateOnlineUsers => {
// 这里可以实现其他触发更新在线用户列表的逻辑
// 为简单起见,暂未详细实现
println!("更新在线用户列表事件触发");
}
} }
} }
} }
// 通知所有客户端线程发送 CmdUpdateOnlineUsers 消息 // 通知所有客户端线程发送 CmdUpdateOnlineUsers 消息
async fn notify_all_clients_to_update_online_users() { async fn notify_all_clients_to_update_online_users() {
let senders = CLIENT_SENDERS.read().await; println!("尝试发送在新用户更新消息体,目前总人数为:{}", CLIENT_SENDERS.len());
for (from_id, sender) in senders.iter() { for entry in CLIENT_SENDERS.iter() {
let sender: &mpsc::Sender<ClientMessage> = entry.value();
let from_id = entry.key();
if let Err(e) = sender.send(ClientMessage::CmdUpdateOnlineUsers).await { if let Err(e) = sender.send(ClientMessage::CmdUpdateOnlineUsers).await {
println!("通知客户端 {} 更新在线用户列表失败: {:?}", from_id, e); println!("通知客户端 {} 更新在线用户列表失败: {:?}", from_id, e);
} else {
println!("通知客户端 {} 更新在线用户列表成功 ===> $$$", from_id);
} }
} }
} }
use crate::handles::redis::remove_this_connection;
pub async fn handle_connection_error(from_id: &str) {
println!("开始处理用户id: {} 的连接错误", from_id);
// 从 Redis 中移除该用户的信息
if let Err(e) = remove_this_connection(from_id).await {
println!("从 Redis 中移除用户信息时出错: {}", e);
}
}
...@@ -8,7 +8,6 @@ pub(crate) async fn handle_other_message( ...@@ -8,7 +8,6 @@ pub(crate) async fn handle_other_message(
data: &ClientMessageData, data: &ClientMessageData,
from_id: &str, from_id: &str,
) -> Result<(), Error> { ) -> Result<(), Error> {
println!("收到客户端消息: {:?}", data); println!("收到客户端消息: {:?} 来自用户id: {}", data, &from_id);
Ok(()) Ok(())
} }
use crate::utils::json_utils; use crate::utils::json_utils;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Instant;
pub fn handle_heartbeat(last_time: &mut Instant) {
*last_time = Instant::now();
}
// 定义服务器心跳数据消息结构 // 定义服务器心跳数据消息结构
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
......
pub mod close_connection;
pub mod handle_messages; pub mod handle_messages;
pub mod handshake; pub mod handshake;
pub mod heartbeat; pub mod heartbeat;
pub mod online_users_update; pub mod online_users_update;
pub mod redis; pub mod redis;
mod handle_agora_call;
use futures::SinkExt;
use crate::client::ONLINE_USERS; use crate::client::ONLINE_USERS;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tungstenite::{Error, Message};
use crate::utils::json_utils::get_current_timestamp;
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OnlineUserMessage { pub struct OnlineUserMessage {
...@@ -39,13 +42,35 @@ pub struct ServerOnlineUserMessage { ...@@ -39,13 +42,35 @@ pub struct ServerOnlineUserMessage {
pub time: u128, pub time: u128,
} }
pub async fn send_online_users_and_send(
sender: &mut (impl SinkExt<Message, Error = Error> + Unpin),
from_id: &str,
) -> Result<(), Error> {
let messages = send_online_users_resp()
.await
.map_err(|e| Error::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
let json_message = serde_json::to_string(&ServerOnlineUserMessage {
msg_type: "CmdUpdateOnlineUsers".to_string(),
from_name: "Server".to_string(),
from_id: "0".to_string(),
to_id: from_id.to_string(),
msg_data: messages,
time: get_current_timestamp(),
})
.map_err(|e| Error::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
if let Err(e) = sender.send(Message::text(json_message)).await {
println!("发送在线用户列表消息给用户 {} 失败: {}", from_id, e);
return Err(e);
}
println!("发送在线用户列表消息给用户 {} 成功", from_id);
Ok(())
}
pub async fn send_online_users_resp() -> Result<Vec<OnlineUserMessage>, serde_json::Error> { pub async fn send_online_users_resp() -> Result<Vec<OnlineUserMessage>, serde_json::Error> {
let mut msg_data = Vec::new(); let mut msg_data = Vec::new();
{ {
let online_users = ONLINE_USERS.read().await; for entry in ONLINE_USERS.iter() {
println!("当前所有用户数据信息 ONLINE_USERS: {:?}", online_users); let user_info_str: &String = entry.value();
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 {
......
...@@ -25,9 +25,7 @@ pub async fn remove_this_connection(from_id: &str) -> Result<(), redis::RedisErr ...@@ -25,9 +25,7 @@ pub async fn remove_this_connection(from_id: &str) -> Result<(), redis::RedisErr
} }
{ {
// 获取写锁以进行写操作 ONLINE_USERS.remove(from_id);
let mut online_users = ONLINE_USERS.write().await;
online_users.remove(from_id);
println!("成功从全局变量中移除用户id: {} 的信息", from_id); println!("成功从全局变量中移除用户id: {} 的信息", from_id);
} }
Ok(()) Ok(())
...@@ -62,8 +60,7 @@ pub async fn insert_this_connection( ...@@ -62,8 +60,7 @@ pub async fn insert_this_connection(
{ {
// 获取写锁以进行写操作 // 获取写锁以进行写操作
let mut online_users = ONLINE_USERS.write().await; ONLINE_USERS.insert(from_id.to_string(), user_info_str);
online_users.insert(from_id.to_string(), user_info_str);
println!("成功将用户id: {} 的信息插入到 ONLINE_USERS 中", from_id); println!("成功将用户id: {} 的信息插入到 ONLINE_USERS 中", from_id);
} }
Ok(()) Ok(())
......
...@@ -6,6 +6,7 @@ mod events; ...@@ -6,6 +6,7 @@ mod events;
mod handles; mod handles;
mod typing; mod typing;
mod utils; mod utils;
mod deport;
use crate::events::handle_events; use crate::events::handle_events;
use client::handle_client; use client::handle_client;
......
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