i am programming a multiplayer game. for each connection i wait for a spawn command from the client and then send the client information (id and the server_message_tx) to the game calculation tokio task. my problem is that the server_message_tx (sender) doesnt seem to work anymore after being passed through the channel, but its only a clone of its original. the original server_message_tx does still work. by working i mean that the receiver doesnt get the messages and the sender after a few messages gets send error because channel is full.
#tokio::sync::mpsc::Receiver not receiving from cloned sender that got passed through a channel?
17 messages · Page 1 of 1 (latest)
i marked some test sections with // TEMP to see if the channel was working at that point
the problem occurs in this part. the server_message_tx_clone successfully arives but sending messages from the other side with it doesnt work
other side of the channel looks like this:
That try_recv is suspicious
What happens when it returns None?
Anyway, you're most likely blocking the thread. see:
https://ryhl.io/blog/async-what-is-blocking/
The async/await feature in Rust is implemented using a mechanism known as cooperative scheduling, and this has some important consequences for people who write asynchronous Rust code.
it continues with the game calculation, which happens because the broadcast function at the end gets executed permamently
loop {
// get new client channels
while let Ok(sender) = {sender_receiver.try_recv()} {
println!("getting sender");
// TEMP doesnt work
sender.sender.try_send(Arc::new(ServerMessage::dummy()));
server_message_senders.push(sender);
}
// delta time calculation here
let now = Instant::now();
let delta_time = now.duration_since(last_time);
last_time = now;
let delta_seconds = delta_time.as_secs_f64();
// receive client input
while let Ok(client_message) = client_message_receiver.try_recv() {
let result = client_message.request_data.execute(&mut game_objects, delta_seconds).log();
}
// game logic calculation
let update_result = update_game(&mut game_objects, delta_seconds).log();
// creating message for sending
let object_data = ObjectData {
game_objects
};
let server_message = ServerMessage {
request_info: RequestInfo::new(get_time() as f64),
request_data: object_data,
};
// sending message
broadcast(&mut server_message_senders, &server_message, delta_seconds);
// retrieving ownership of data
game_objects = server_message.request_data.game_objects;
}
I don't see any .await in that loop. Read the article I linked to understand why that's important.
i understand what you are saying, but the thread is not blocking here, or at least that wouldnt be a permanent block
i know that because the broadcast function gives me the feedback that the channel appears to be full after a while
pub fn broadcast(senders: &mut Vec<ServerMessageSenderChannel>, message: &ServerMessage, delta_seconds: f64) {
let shared_message = Arc::new(message.clone()); // Wrap the message in an Arc
let mut to_be_removed = Vec::<usize>::new();
// send messages to all
for (i, sender_channel) in senders.iter_mut().enumerate() {
sender_channel.tick_counter += delta_seconds;
if sender_channel.tick_counter >= sender_channel.update_threshold {
// send message to client
println!("trying to send to client");
sender_channel.tick_counter = 0.;
let message_clone = Arc::clone(&shared_message);
if let Err(e) = sender_channel.sender.try_send(message_clone) {
match e {
error::TrySendError::Full(_) => {
eprintln!("Failed to send message: {}", e);
},
error::TrySendError::Closed(_) => {
eprintln!("Failed to send message: {}", e);
// remove connection
to_be_removed.push(i);
},
};
}
}
else {
// println!("tick not there yet {} - {}", sender_channel.tick_counter, sender_channel.update_threshold);
}
}
// remove senders that are closed
for i in to_be_removed.iter().rev() {
senders.remove(*i);
}
}
Can you try using tokio-console and sharing what it says?
let me look up what that is, i am pretty new to tokio
sorry can i continue later? i got a groupwork todo now
Of course