|
1 | 1 | use open_coroutine::task; |
2 | 2 | use std::io::{Error, IoSlice, IoSliceMut, Read, Write}; |
3 | | -use std::net::{Shutdown, TcpListener, ToSocketAddrs}; |
| 3 | +use std::net::{Shutdown, SocketAddr, TcpListener}; |
4 | 4 | #[cfg(unix)] |
5 | 5 | use std::os::fd::AsRawFd; |
6 | 6 | use std::sync::{Arc, Condvar, Mutex}; |
7 | 7 | use std::time::Duration; |
8 | 8 |
|
9 | | -pub fn start_co_server<A: ToSocketAddrs>( |
10 | | - addr: A, |
| 9 | +pub fn start_co_server( |
11 | 10 | server_finished: Arc<(Mutex<bool>, Condvar)>, |
12 | | - server_started: Arc<(Mutex<bool>, Condvar)>, |
| 11 | + server_started: Arc<(Mutex<Option<SocketAddr>>, Condvar)>, |
13 | 12 | ) { |
14 | | - let listener = TcpListener::bind(addr).expect("start server failed"); |
| 13 | + let listener = TcpListener::bind("127.0.0.1:0").expect("start server failed"); |
| 14 | + let local_addr = listener.local_addr().expect("get local addr failed"); |
15 | 15 | // Signal that server is ready to accept connections |
16 | 16 | { |
17 | 17 | let (lock, cvar) = &*server_started; |
18 | | - let mut started = lock.lock().unwrap(); |
19 | | - *started = true; |
| 18 | + let mut addr = lock.lock().unwrap(); |
| 19 | + *addr = Some(local_addr); |
20 | 20 | cvar.notify_one(); |
21 | 21 | } |
22 | 22 | for stream in listener.incoming() { |
@@ -88,14 +88,15 @@ pub fn start_co_server<A: ToSocketAddrs>( |
88 | 88 | } |
89 | 89 | } |
90 | 90 |
|
91 | | -pub fn start_client<A: ToSocketAddrs>(addr: A, server_started: Arc<(Mutex<bool>, Condvar)>) { |
92 | | - // Wait for server to be ready |
93 | | - { |
| 91 | +pub fn start_client(server_started: Arc<(Mutex<Option<SocketAddr>>, Condvar)>) { |
| 92 | + // Wait for server to be ready and get the actual address |
| 93 | + let addr = { |
94 | 94 | let (lock, cvar) = &*server_started; |
95 | | - let _guard = cvar |
96 | | - .wait_while(lock.lock().unwrap(), |started| !*started) |
| 95 | + let guard = cvar |
| 96 | + .wait_while(lock.lock().unwrap(), |addr| addr.is_none()) |
97 | 97 | .unwrap(); |
98 | | - } |
| 98 | + guard.unwrap() |
| 99 | + }; |
99 | 100 | let mut stream = |
100 | 101 | open_coroutine::connect_timeout(addr, Duration::from_secs(3)).expect("connect failed"); |
101 | 102 | let mut buffer1 = [0; 256]; |
@@ -169,18 +170,17 @@ pub fn start_client<A: ToSocketAddrs>(addr: A, server_started: Arc<(Mutex<bool>, |
169 | 170 |
|
170 | 171 | #[open_coroutine::main(event_loop_size = 1, max_size = 1)] |
171 | 172 | pub fn main() -> std::io::Result<()> { |
172 | | - let addr = "127.0.0.1:8889"; |
173 | 173 | let server_finished_pair = Arc::new((Mutex::new(true), Condvar::new())); |
174 | 174 | let server_finished = Arc::clone(&server_finished_pair); |
175 | | - let server_started_pair = Arc::new((Mutex::new(false), Condvar::new())); |
| 175 | + let server_started_pair = Arc::new((Mutex::new(None), Condvar::new())); |
176 | 176 | let server_started = Arc::clone(&server_started_pair); |
177 | 177 | _ = std::thread::Builder::new() |
178 | 178 | .name("crate_co_server".to_string()) |
179 | | - .spawn(move || start_co_server(addr, server_finished_pair, server_started_pair)) |
| 179 | + .spawn(move || start_co_server(server_finished_pair, server_started_pair)) |
180 | 180 | .expect("failed to spawn thread"); |
181 | 181 | _ = std::thread::Builder::new() |
182 | 182 | .name("crate_client".to_string()) |
183 | | - .spawn(move || start_client(addr, server_started)) |
| 183 | + .spawn(move || start_client(server_started)) |
184 | 184 | .expect("failed to spawn thread"); |
185 | 185 |
|
186 | 186 | let (lock, cvar) = &*server_finished; |
|
0 commit comments