Skip to content

Commit 872bc09

Browse files
author
Andrew Liu
authored
examples: update chat example (#3587)
1 parent db1d904 commit 872bc09

2 files changed

Lines changed: 31 additions & 70 deletions

File tree

examples/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ tokio = { version = "1.0.0", features = ["full", "tracing"] }
1111
tokio-util = { version = "0.6.3", features = ["full"] }
1212
tokio-stream = { version = "0.1" }
1313

14-
async-stream = "0.3"
1514
tracing = "0.1"
1615
tracing-subscriber = { version = "0.2.7", default-features = false, features = ["fmt", "ansi", "env-filter", "chrono", "tracing-log"] }
1716
bytes = "1.0.0"

examples/chat.rs

Lines changed: 31 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,16 @@
2828

2929
use tokio::net::{TcpListener, TcpStream};
3030
use tokio::sync::{mpsc, Mutex};
31-
use tokio_stream::{Stream, StreamExt};
32-
use tokio_util::codec::{Framed, LinesCodec, LinesCodecError};
31+
use tokio_stream::StreamExt;
32+
use tokio_util::codec::{Framed, LinesCodec};
3333

3434
use futures::SinkExt;
3535
use std::collections::HashMap;
3636
use std::env;
3737
use std::error::Error;
3838
use std::io;
3939
use std::net::SocketAddr;
40-
use std::pin::Pin;
4140
use std::sync::Arc;
42-
use std::task::{Context, Poll};
4341

4442
#[tokio::main]
4543
async fn main() -> Result<(), Box<dyn Error>> {
@@ -101,6 +99,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
10199
/// Shorthand for the transmit half of the message channel.
102100
type Tx = mpsc::UnboundedSender<String>;
103101

102+
/// Shorthand for the receive half of the message channel.
103+
type Rx = mpsc::UnboundedReceiver<String>;
104+
104105
/// Data that is shared between all peers in the chat server.
105106
///
106107
/// This is the set of `Tx` handles for all connected clients. Whenever a
@@ -124,7 +125,7 @@ struct Peer {
124125
///
125126
/// This is used to receive messages from peers. When a message is received
126127
/// off of this `Rx`, it will be written to the socket.
127-
rx: Pin<Box<dyn Stream<Item = String> + Send>>,
128+
rx: Rx,
128129
}
129130

130131
impl Shared {
@@ -156,58 +157,15 @@ impl Peer {
156157
let addr = lines.get_ref().peer_addr()?;
157158

158159
// Create a channel for this peer
159-
let (tx, mut rx) = mpsc::unbounded_channel();
160+
let (tx, rx) = mpsc::unbounded_channel();
160161

161162
// Add an entry for this `Peer` in the shared state map.
162163
state.lock().await.peers.insert(addr, tx);
163164

164-
let rx = Box::pin(async_stream::stream! {
165-
while let Some(item) = rx.recv().await {
166-
yield item;
167-
}
168-
});
169-
170165
Ok(Peer { lines, rx })
171166
}
172167
}
173168

174-
#[derive(Debug)]
175-
enum Message {
176-
/// A message that should be broadcasted to others.
177-
Broadcast(String),
178-
179-
/// A message that should be received by a client
180-
Received(String),
181-
}
182-
183-
// Peer implements `Stream` in a way that polls both the `Rx`, and `Framed` types.
184-
// A message is produced whenever an event is ready until the `Framed` stream returns `None`.
185-
impl Stream for Peer {
186-
type Item = Result<Message, LinesCodecError>;
187-
188-
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
189-
// First poll the `UnboundedReceiver`.
190-
191-
if let Poll::Ready(Some(v)) = Pin::new(&mut self.rx).poll_next(cx) {
192-
return Poll::Ready(Some(Ok(Message::Received(v))));
193-
}
194-
195-
// Secondly poll the `Framed` stream.
196-
let result: Option<_> = futures::ready!(Pin::new(&mut self.lines).poll_next(cx));
197-
198-
Poll::Ready(match result {
199-
// We've received a message we should broadcast to others.
200-
Some(Ok(message)) => Some(Ok(Message::Broadcast(message))),
201-
202-
// An error occurred.
203-
Some(Err(e)) => Some(Err(e)),
204-
205-
// The stream has been exhausted.
206-
None => None,
207-
})
208-
}
209-
}
210-
211169
/// Process an individual chat client
212170
async fn process(
213171
state: Arc<Mutex<Shared>>,
@@ -241,28 +199,32 @@ async fn process(
241199
}
242200

243201
// Process incoming messages until our stream is exhausted by a disconnect.
244-
while let Some(result) = peer.next().await {
245-
match result {
246-
// A message was received from the current user, we should
247-
// broadcast this message to the other users.
248-
Ok(Message::Broadcast(msg)) => {
249-
let mut state = state.lock().await;
250-
let msg = format!("{}: {}", username, msg);
251-
252-
state.broadcast(addr, &msg).await;
253-
}
254-
// A message was received from a peer. Send it to the
255-
// current user.
256-
Ok(Message::Received(msg)) => {
202+
loop {
203+
tokio::select! {
204+
// A message was received from a peer. Send it to the current user.
205+
Some(msg) = peer.rx.recv() => {
257206
peer.lines.send(&msg).await?;
258207
}
259-
Err(e) => {
260-
tracing::error!(
261-
"an error occurred while processing messages for {}; error = {:?}",
262-
username,
263-
e
264-
);
265-
}
208+
result = peer.lines.next() => match result {
209+
// A message was received from the current user, we should
210+
// broadcast this message to the other users.
211+
Some(Ok(msg)) => {
212+
let mut state = state.lock().await;
213+
let msg = format!("{}: {}", username, msg);
214+
215+
state.broadcast(addr, &msg).await;
216+
}
217+
// An error occurred.
218+
Some(Err(e)) => {
219+
tracing::error!(
220+
"an error occurred while processing messages for {}; error = {:?}",
221+
username,
222+
e
223+
);
224+
}
225+
// The stream has been exhausted.
226+
None => break,
227+
},
266228
}
267229
}
268230

0 commit comments

Comments
 (0)