@@ -13,56 +13,70 @@ use websocket::{ClientBuilder, OwnedMessage};
13
13
14
14
const CONNECTION : & ' static str = "ws://127.0.0.1:2794" ;
15
15
16
+ // Async websocket chat client
16
17
fn main ( ) {
17
18
println ! ( "Connecting to {}" , CONNECTION ) ;
19
+
20
+ // Construct new Tokio runtime environment
18
21
let mut runtime = tokio:: runtime:: current_thread:: Builder :: new ( )
19
22
. build ( )
20
23
. unwrap ( ) ;
21
24
22
- // standard in isn't supported in mio yet, so we use a thread
23
- // see https://github.com/carllerche/mio/issues/321
24
25
let ( usr_msg, stdin_ch) = mpsc:: channel ( 0 ) ;
26
+
27
+ // Spawn new thread to read user input
28
+ // stdin isn't supported in mio yet, so we use a thread
29
+ // see https://github.com/carllerche/mio/issues/321
25
30
thread:: spawn ( || {
26
31
let mut input = String :: new ( ) ;
27
32
let mut stdin_sink = usr_msg. wait ( ) ;
28
33
loop {
34
+ // Read user input from stdin
29
35
input. clear ( ) ;
30
36
stdin ( ) . read_line ( & mut input) . unwrap ( ) ;
37
+
38
+ // Trim whitespace and match input to known chat commands
39
+ // If input is unknown, send trimmed input as a chat message
31
40
let trimmed = input. trim ( ) ;
32
-
33
41
let ( close, msg) = match trimmed {
34
42
"/close" => ( true , OwnedMessage :: Close ( None ) ) ,
35
43
"/ping" => ( false , OwnedMessage :: Ping ( b"PING" . to_vec ( ) ) ) ,
36
44
_ => ( false , OwnedMessage :: Text ( trimmed. to_string ( ) ) ) ,
37
45
} ;
38
-
46
+ // Send message to websocket server
39
47
stdin_sink
40
48
. send ( msg)
41
49
. expect ( "Sending message across stdin channel." ) ;
42
-
50
+ // If user entered the "/close" command, break the loop
43
51
if close {
44
52
break ;
45
53
}
46
54
}
47
55
} ) ;
48
56
57
+ // Construct a new connection to the websocket server
49
58
let runner = ClientBuilder :: new ( CONNECTION )
50
59
. unwrap ( )
51
60
. add_protocol ( "rust-websocket" )
52
61
. async_connect_insecure ( )
53
62
. and_then ( |( duplex, _) | {
54
63
let ( sink, stream) = duplex. split ( ) ;
55
64
stream
65
+ // Iterate over message as they arrive in stream
56
66
. filter_map ( |message| {
57
67
println ! ( "Received Message: {:?}" , message) ;
68
+ // Respond to close or ping commands from the server
58
69
match message {
59
70
OwnedMessage :: Close ( e) => Some ( OwnedMessage :: Close ( e) ) ,
60
71
OwnedMessage :: Ping ( d) => Some ( OwnedMessage :: Pong ( d) ) ,
61
72
_ => None ,
62
73
}
63
74
} )
75
+ // Takes in messages from both sinks
64
76
. select ( stdin_ch. map_err ( |_| WebSocketError :: NoDataAvailable ) )
77
+ // Return a future that completes once all incoming data from the above streams has been processed into the sink
65
78
. forward ( sink)
66
79
} ) ;
80
+ // Start our websocket client runner in the Tokio environment
67
81
runtime. block_on ( runner) . unwrap ( ) ;
68
82
}
0 commit comments