@@ -1560,6 +1560,104 @@ <h2 id="_handling_disconnections">Handling Disconnections</h2>
1560
1560
</ div >
1561
1561
</ div >
1562
1562
</ div >
1563
+ < div class ="sect1 ">
1564
+ < h2 id ="_implementing_a_client "> Implementing a client</ h2 >
1565
+ < div class ="sectionbody ">
1566
+ < div class ="paragraph ">
1567
+ < p > Let’s now implement the client for the chat.
1568
+ Because the protocol is line-based, the implementation is pretty straightforward:</ p >
1569
+ </ div >
1570
+ < div class ="ulist ">
1571
+ < ul >
1572
+ < li >
1573
+ < p > Lines read from stdin should be send over the socket.</ p >
1574
+ </ li >
1575
+ < li >
1576
+ < p > Lines read from the socket should be echoed to stdout.</ p >
1577
+ </ li >
1578
+ </ ul >
1579
+ </ div >
1580
+ < div class ="paragraph ">
1581
+ < p > Unlike the server, the client needs only limited concurrency, as it interacts with only a single user.
1582
+ For this reason, async doesn’t bring a lot of performance benefits in this case.</ p >
1583
+ </ div >
1584
+ < div class ="paragraph ">
1585
+ < p > However, async is still useful for managing concurrency!
1586
+ Specifically, the client should < em > simultaneously</ em > read from stdin and from the socket.
1587
+ Programming this with threads is cumbersome, especially when implementing clean shutdown.
1588
+ With async, we can just use the < code > select!</ code > macro.</ p >
1589
+ </ div >
1590
+ < div class ="listingblock ">
1591
+ < div class ="content ">
1592
+ < pre class ="pygments highlight "> < code data-lang ="rust "> < span > </ span > < span class ="tok-cp "> #![feature(async_await)]</ span > < span class ="tok-w "> </ span >
1593
+
1594
+ < span class ="tok-k "> use</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> std</ span > ::< span class ="tok-n "> net</ span > ::< span class ="tok-n "> ToSocketAddrs</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1595
+
1596
+ < span class ="tok-k "> use</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> futures</ span > ::< span class ="tok-n "> select</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1597
+
1598
+ < span class ="tok-k "> use</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> async_std</ span > ::< span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1599
+ < span class ="tok-w "> </ span > < span class ="tok-n "> prelude</ span > ::< span class ="tok-o "> *</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span >
1600
+ < span class ="tok-w "> </ span > < span class ="tok-n "> net</ span > ::< span class ="tok-n "> TcpStream</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span >
1601
+ < span class ="tok-w "> </ span > < span class ="tok-n "> task</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span >
1602
+ < span class ="tok-w "> </ span > < span class ="tok-n "> io</ span > ::< span class ="tok-p "> {</ span > < span class ="tok-n "> stdin</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> BufReader</ span > < span class ="tok-p "> },</ span > < span class ="tok-w "> </ span >
1603
+ < span class ="tok-p "> };</ span > < span class ="tok-w "> </ span >
1604
+
1605
+ < span class ="tok-k "> type</ span > < span class ="tok-nb "> Result</ span > < span class ="tok-o "> <</ span > < span class ="tok-n "> T</ span > < span class ="tok-o "> ></ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> std</ span > ::< span class ="tok-n "> result</ span > ::< span class ="tok-nb "> Result</ span > < span class ="tok-o "> <</ span > < span class ="tok-n "> T</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span > < span class ="tok-nb "> Box</ span > < span class ="tok-o "> <</ span > < span class ="tok-n "> dyn</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> std</ span > ::< span class ="tok-n "> error</ span > ::< span class ="tok-n "> Error</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> +</ span > < span class ="tok-w "> </ span > < span class ="tok-nb "> Send</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> +</ span > < span class ="tok-w "> </ span > < span class ="tok-nb "> Sync</ span > < span class ="tok-o "> >></ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1606
+
1607
+
1608
+ < span class ="tok-k "> fn</ span > < span class ="tok-nf "> main</ span > < span class ="tok-p "> ()</ span > < span class ="tok-w "> </ span > -> < span class ="tok-nb "> Result</ span > < span class ="tok-o "> <</ span > < span class ="tok-p "> ()</ span > < span class ="tok-o "> ></ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1609
+ < span class ="tok-w "> </ span > < span class ="tok-n "> task</ span > ::< span class ="tok-n "> block_on</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> try_main</ span > < span class ="tok-p "> (</ span > < span class ="tok-s "> "127.0.0.1:8080"</ span > < span class ="tok-p "> ))</ span > < span class ="tok-w "> </ span >
1610
+ < span class ="tok-p "> }</ span > < span class ="tok-w "> </ span >
1611
+
1612
+ < span class ="tok-n "> async</ span > < span class ="tok-w "> </ span > < span class ="tok-k "> fn</ span > < span class ="tok-nf "> try_main</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> addr</ span > : < span class ="tok-nc "> impl</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> ToSocketAddrs</ span > < span class ="tok-p "> )</ span > < span class ="tok-w "> </ span > -> < span class ="tok-nb "> Result</ span > < span class ="tok-o "> <</ span > < span class ="tok-p "> ()</ span > < span class ="tok-o "> ></ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1613
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> stream</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> TcpStream</ span > ::< span class ="tok-n "> connect</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> addr</ span > < span class ="tok-p "> ).</ span > < span class ="tok-n "> await</ span > < span class ="tok-o "> ?</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1614
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> reader</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span > < span class ="tok-k "> mut</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> writer</ span > < span class ="tok-p "> )</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-p "> (</ span > < span class ="tok-o "> &</ span > < span class ="tok-n "> stream</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> &</ span > < span class ="tok-n "> stream</ span > < span class ="tok-p "> );</ span > < span class ="tok-w "> </ span > < i class ="conum " data-value ="1 "> </ i > < b > (1)</ b >
1615
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> reader</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> BufReader</ span > ::< span class ="tok-n "> new</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> reader</ span > < span class ="tok-p "> );</ span > < span class ="tok-w "> </ span >
1616
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-k "> mut</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> lines_from_server</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> futures</ span > ::< span class ="tok-n "> StreamExt</ span > ::< span class ="tok-n "> fuse</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> reader</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> lines</ span > < span class ="tok-p "> ());</ span > < span class ="tok-w "> </ span > < i class ="conum " data-value ="2 "> </ i > < b > (2)</ b >
1617
+
1618
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> stdin</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> BufReader</ span > ::< span class ="tok-n "> new</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> stdin</ span > < span class ="tok-p "> ());</ span > < span class ="tok-w "> </ span >
1619
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-k "> mut</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> lines_from_stdin</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> futures</ span > ::< span class ="tok-n "> StreamExt</ span > ::< span class ="tok-n "> fuse</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> stdin</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> lines</ span > < span class ="tok-p "> ());</ span > < span class ="tok-w "> </ span > < i class ="conum " data-value ="2 "> </ i > < b > (2)</ b >
1620
+ < span class ="tok-w "> </ span > < span class ="tok-k "> loop</ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1621
+ < span class ="tok-w "> </ span > < span class ="tok-n "> select</ span > < span class ="tok-o "> !</ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span > < i class ="conum " data-value ="3 "> </ i > < b > (3)</ b >
1622
+ < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> lines_from_server</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> next</ span > < span class ="tok-p "> ()</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =></ span > < span class ="tok-w "> </ span > < span class ="tok-k "> match</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1623
+ < span class ="tok-w "> </ span > < span class ="tok-nb "> Some</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> line</ span > < span class ="tok-p "> )</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =></ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1624
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-o "> ?</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1625
+ < span class ="tok-w "> </ span > < span class ="tok-n "> println</ span > < span class ="tok-o "> !</ span > < span class ="tok-p "> (</ span > < span class ="tok-s "> "{}"</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-p "> );</ span > < span class ="tok-w "> </ span >
1626
+ < span class ="tok-w "> </ span > < span class ="tok-p "> },</ span > < span class ="tok-w "> </ span >
1627
+ < span class ="tok-w "> </ span > < span class ="tok-nb "> None</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =></ span > < span class ="tok-w "> </ span > < span class ="tok-k "> break</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span >
1628
+ < span class ="tok-w "> </ span > < span class ="tok-p "> },</ span > < span class ="tok-w "> </ span >
1629
+ < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> lines_from_stdin</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> next</ span > < span class ="tok-p "> ()</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =></ span > < span class ="tok-w "> </ span > < span class ="tok-k "> match</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1630
+ < span class ="tok-w "> </ span > < span class ="tok-nb "> Some</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> line</ span > < span class ="tok-p "> )</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =></ span > < span class ="tok-w "> </ span > < span class ="tok-p "> {</ span > < span class ="tok-w "> </ span >
1631
+ < span class ="tok-w "> </ span > < span class ="tok-kd "> let</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =</ span > < span class ="tok-w "> </ span > < span class ="tok-n "> line</ span > < span class ="tok-o "> ?</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1632
+ < span class ="tok-w "> </ span > < span class ="tok-n "> writer</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> write_all</ span > < span class ="tok-p "> (</ span > < span class ="tok-n "> line</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> as_bytes</ span > < span class ="tok-p "> ()).</ span > < span class ="tok-n "> await</ span > < span class ="tok-o "> ?</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1633
+ < span class ="tok-w "> </ span > < span class ="tok-n "> writer</ span > < span class ="tok-p "> .</ span > < span class ="tok-n "> write_all</ span > < span class ="tok-p "> (</ span > < span class ="tok-s "> b"</ span > < span class ="tok-se "> \n</ span > < span class ="tok-s "> "</ span > < span class ="tok-p "> ).</ span > < span class ="tok-n "> await</ span > < span class ="tok-o "> ?</ span > < span class ="tok-p "> ;</ span > < span class ="tok-w "> </ span >
1634
+ < span class ="tok-w "> </ span > < span class ="tok-p "> }</ span > < span class ="tok-w "> </ span >
1635
+ < span class ="tok-w "> </ span > < span class ="tok-nb "> None</ span > < span class ="tok-w "> </ span > < span class ="tok-o "> =></ span > < span class ="tok-w "> </ span > < span class ="tok-k "> break</ span > < span class ="tok-p "> ,</ span > < span class ="tok-w "> </ span >
1636
+ < span class ="tok-w "> </ span > < span class ="tok-p "> }</ span > < span class ="tok-w "> </ span >
1637
+ < span class ="tok-w "> </ span > < span class ="tok-p "> }</ span > < span class ="tok-w "> </ span >
1638
+ < span class ="tok-w "> </ span > < span class ="tok-p "> }</ span > < span class ="tok-w "> </ span >
1639
+ < span class ="tok-w "> </ span > < span class ="tok-nb "> Ok</ span > < span class ="tok-p "> (())</ span > < span class ="tok-w "> </ span >
1640
+ < span class ="tok-p "> }</ span > < span class ="tok-w "> </ span > </ code > </ pre >
1641
+ </ div >
1642
+ </ div >
1643
+ < div class ="colist arabic ">
1644
+ < table >
1645
+ < tr >
1646
+ < td > < i class ="conum " data-value ="1 "> </ i > < b > 1</ b > </ td >
1647
+ < td > Here we split < code > TcpStream</ code > into read and write halfs: there’s < code > impl AsyncRead for &'_ TcpStream</ code > , just like the one in std.</ td >
1648
+ </ tr >
1649
+ < tr >
1650
+ < td > < i class ="conum " data-value ="2 "> </ i > < b > 2</ b > </ td >
1651
+ < td > We crate a steam of lines for both the socket and stdin.</ td >
1652
+ </ tr >
1653
+ < tr >
1654
+ < td > < i class ="conum " data-value ="3 "> </ i > < b > 3</ b > </ td >
1655
+ < td > In the main select loop, we print the lines we receive from server and send the lines we read from the console.</ td >
1656
+ </ tr >
1657
+ </ table >
1658
+ </ div >
1659
+ </ div >
1660
+ </ div >
1563
1661
</ div >
1564
1662
< div id ="footer ">
1565
1663
< div id ="footer-text ">
0 commit comments