Setup a server-client program.
I setup a server-client program where the server will terminate when Ctrl+C is pressed.
This commit is contained in:
parent
15ae16abb0
commit
a965f796ae
1546
Cargo.lock
generated
Normal file
1546
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
16
Cargo.toml
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "satellite"
|
name = "satellite"
|
||||||
version = "0.0.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Rust Challenge"
|
description = "Rust Challenge"
|
||||||
repository = "/myrddin/satellite"
|
repository = "/myrddin/satellite"
|
||||||
@ -10,4 +10,18 @@ license-file = "LICENSE.md"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "satellite"
|
||||||
|
path = "src/server.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "base_station"
|
||||||
|
path = "src/client.rs"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
clap = { version = "4.5.32", features = ["derive"] }
|
||||||
|
chrono = "0.4.40"
|
||||||
|
tokio = { version = "1.44.1", features = ["macros", "rt-multi-thread", "io-std", "fs", "signal", "sync"] }
|
||||||
|
console-subscriber = "0.4.1"
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
# satellite
|
# Satellite Propulsion Simulation
|
||||||
|
|
||||||
Rust Challenge
|
## Design Approach
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
### Build
|
||||||
|
### Run
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
//! Rust Challenge
|
//! Rust Challenge
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mod project;
|
mod project;
|
||||||
|
|
||||||
|
|
||||||
|
/// The environment variable defined by Cargo for the name.
|
||||||
|
const CLIENT_NAME: &'static str = "base_station";
|
||||||
|
|
||||||
|
|
||||||
/// Print the version of the project.
|
/// Print the version of the project.
|
||||||
fn print_version()
|
fn print_version()
|
||||||
{
|
{
|
||||||
println!("{} v{}", project::get_name(), project::get_version());
|
println!("{} v{}", CLIENT_NAME, project::get_version());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/// The environment variable defined by Cargo for the name.
|
/// The environment variable defined by Cargo for the name.
|
||||||
|
#[allow(dead_code)]
|
||||||
const NAME: Option<&str> = option_env!("CARGO_PKG_NAME");
|
const NAME: Option<&str> = option_env!("CARGO_PKG_NAME");
|
||||||
|
|
||||||
/// The environment variable defined by Cargo for the version.
|
/// The environment variable defined by Cargo for the version.
|
||||||
@ -17,6 +18,7 @@ const NOT_DEFINED: &'static str = "UNDEFINED";
|
|||||||
/// set at compile time and comes from the Cargo.toml file.
|
/// set at compile time and comes from the Cargo.toml file.
|
||||||
///
|
///
|
||||||
/// If a value is not found, then it will return the not defined value.
|
/// If a value is not found, then it will return the not defined value.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn get_name() -> &'static str
|
pub fn get_name() -> &'static str
|
||||||
{
|
{
|
||||||
NAME.unwrap_or(NOT_DEFINED)
|
NAME.unwrap_or(NOT_DEFINED)
|
||||||
|
84
src/server.rs
Normal file
84
src/server.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//! Rust Challenge: Satellite Propulsion Sim
|
||||||
|
|
||||||
|
mod project;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use tokio::sync::watch;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type IoResult<T> = Result<T, io::Error>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Print the version of the project.
|
||||||
|
fn print_version()
|
||||||
|
{
|
||||||
|
println!("{} v{}", project::get_name(), project::get_version());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asynchronously listen for CTRL-C to be pressed.
|
||||||
|
///
|
||||||
|
/// Sends `false` through the watch channel when the signal is received.
|
||||||
|
async fn listen_for_termination(sender: watch::Sender<bool>) -> IoResult<()>
|
||||||
|
{
|
||||||
|
tokio::signal::ctrl_c().await?;
|
||||||
|
|
||||||
|
println!("\nReceived Ctrl+C, initiating shutdown...");
|
||||||
|
|
||||||
|
// Send termination message to all listeners
|
||||||
|
sender.send_replace(false);
|
||||||
|
sender.closed().await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Program entry point.
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> IoResult<()>
|
||||||
|
{
|
||||||
|
print_version();
|
||||||
|
|
||||||
|
let (term_sender, mut term_receiver) = watch::channel(true);
|
||||||
|
|
||||||
|
// Spawn a task to handle termination signal.
|
||||||
|
let term_task =
|
||||||
|
tokio::spawn(async move { listen_for_termination(term_sender).await });
|
||||||
|
|
||||||
|
// Spawn a task to listen for network communication.
|
||||||
|
let comm_task = tokio::spawn(async move {
|
||||||
|
let mut running = true;
|
||||||
|
while running
|
||||||
|
{
|
||||||
|
tokio::select! {
|
||||||
|
_ = term_receiver.changed() => {
|
||||||
|
println!("Communication task received shutdown message.");
|
||||||
|
running = *term_receiver.borrow_and_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for termination signal task and propagate any error.
|
||||||
|
match term_task.await
|
||||||
|
{
|
||||||
|
Ok(Ok(())) =>
|
||||||
|
{}
|
||||||
|
Ok(Err(e)) => return Err(e),
|
||||||
|
Err(e) =>
|
||||||
|
{
|
||||||
|
eprintln!("Termination task panicked: {}", e);
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other,
|
||||||
|
"Termination task panicked"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the communication task to complete.
|
||||||
|
let _ = comm_task.await;
|
||||||
|
|
||||||
|
println!("Shutdown complete.");
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user