Repository navigation
Expand file tree
/
Copy pathsocket_options.rs
More file actions
76 lines (67 loc) · 2.81 KB
/
Copy pathsocket_options.rs
File metadata and controls
76 lines (67 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Released under the MIT License.
// Copyright, 2026, by Samuel Williams.
//! Configure a listener before binding through a generic scheduler. Run with `cargo run -p socketry-executor --example socket_options --features tokio` for both native and Tokio implementations.
use std::io;
#[cfg(any(feature = "native", feature = "tokio"))]
async fn listener<S>(scheduler: &S) -> io::Result<()>
where
S: socketry_executor::SocketOptions<socketry_executor::SocketReuseAddress>
+ socketry_executor::SocketOpen
+ socketry_executor::SocketBind
+ socketry_executor::SocketListen
+ socketry_executor::SocketLocalAddress
+ socketry_executor::SocketClose,
{
use socketry_executor::{Cancellation, SocketDomain, SocketReuseAddress, SocketType};
let cancellation = Cancellation::never();
let socket = scheduler
.socket_open(SocketDomain::Ipv4, SocketType::Stream, None, &cancellation)
.await?;
// The option identifier selects both the capability and its value type. SO_REUSEADDR takes a bool, so another value type would not compile.
// Await configuration before bind. Address-sharing rules remain OS-specific, especially on Windows; choose this policy deliberately for a real server.
scheduler
.socket_set_option(&socket, SocketReuseAddress, true, &cancellation)
.await?;
assert!(
scheduler
.socket_get_option(&socket, SocketReuseAddress, &cancellation)
.await?
);
// Port zero gives this example an available local port. The same descriptor progresses from open to bound to listening.
scheduler
.socket_bind(&socket, "127.0.0.1:0".parse().unwrap(), &cancellation)
.await?;
scheduler.socket_listen(&socket, 16, &cancellation).await?;
println!(
"Configured listener at {}",
scheduler.socket_local_address(&socket)?
);
// A server could now accept connections and explicitly configure TcpNoDelay or SocketKeepalive on each accepted descriptor. This example stops after setup; every operation is complete before consuming close.
scheduler.socket_close(socket).await?;
Ok(())
}
fn main() -> io::Result<()> {
#[cfg(feature = "native")]
{
let scheduler = socketry_executor::Scheduler::with_workers(1)?;
scheduler.block_on(listener(&scheduler))?;
}
#[cfg(feature = "tokio")]
{
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?;
let scheduler =
socketry_executor::scheduler::tokio::Scheduler::new(runtime.handle().clone());
runtime.block_on(listener(&scheduler))?;
runtime.block_on(scheduler.shutdown());
}
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn configure_listener_on_enabled_backends() {
super::main().unwrap();
}
}