Skip to content

Commit 9ca2e50

Browse files
authored
Merge pull request #137 from AndyGauge/listen-tcp-random-port
Added networking example to listen on random socket using tcp/ip
2 parents 3c1d3aa + 10a14ea commit 9ca2e50

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

src/intro.md

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ community. It needs and welcomes help. For details see
6060
| [Query the GitHub API][ex-rest-get] | [![reqwest-badge]][reqwest] [![serde-badge]][serde] | [![cat-net-badge]][cat-net] [![cat-encoding-badge]][cat-encoding] |
6161
| [Check if an API Resource Exists][ex-rest-head] | [![reqwest-badge]][reqwest] | [![cat-net-badge]][cat-net] |
6262
| [Create and delete Gist with GitHub API][ex-rest-post] | [![reqwest-badge]][reqwest] [![serde-badge]][serde] | [![cat-net-badge]][cat-net] [![cat-encoding-badge]][cat-encoding] |
63+
| [Listen on Unused port TCP/IP][ex-random-port-tcp] | [![std-badge]][std] | [![cat-net-badge]][cat-net] |
6364

6465
## [Application development](app.html)
6566

@@ -175,6 +176,7 @@ Keep lines sorted.
175176
[ex-rand-custom]: basics.html#ex-rand-custom
176177
[ex-rand-dist]: basics.html#ex-rand-dist
177178
[ex-rand-float]: basics.html#ex-rand-float
179+
[ex-random-port-tcp]: net.html#ex-random-port-tcp
178180
[ex-rand-range]: basics.html#ex-rand-range
179181
[ex-rayon-iter-mut]: concurrency.html#ex-rayon-iter-mut
180182
[ex-rest-head]: net.html#ex-rest-head

src/net.md

+64
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
| [Query the GitHub API][ex-rest-get] | [![reqwest-badge]][reqwest] [![serde-badge]][serde] | [![cat-net-badge]][cat-net] [![cat-encoding-badge]][cat-encoding] |
1313
| [Check if an API Resource Exists][ex-rest-head] | [![reqwest-badge]][reqwest] | [![cat-net-badge]][cat-net] |
1414
| [Create and delete Gist with GitHub API][ex-rest-post] | [![reqwest-badge]][reqwest] [![serde-badge]][serde] | [![cat-net-badge]][cat-net] [![cat-encoding-badge]][cat-encoding] |
15+
| [Listen on Unused port TCP/IP][ex-random-port-tcp] | [![std-badge]][std] | [![cat-net-badge]][cat-net] |
1516

1617
[ex-url-parse]: #ex-url-parse
1718
<a name="ex-url-parse"/>
@@ -528,6 +529,61 @@ fn run() -> Result<()> {
528529
# quick_main!(run);
529530
```
530531

532+
[ex-random-port-tcp]: #ex-random-port-tcp
533+
<a name="ex-random-port-tcp"></a>
534+
## Listen on Unused port TCP/IP
535+
536+
[![std-badge]][std] [![cat-net-badge]][cat-net]
537+
538+
In this example, the port is displayed on the console, and the program will
539+
listen until a request is made.
540+
541+
```rust, no_run
542+
#[macro_use]
543+
extern crate error_chain;
544+
545+
use std::net::{SocketAddrV4, Ipv4Addr, TcpListener};
546+
use std::io::Read;
547+
548+
error_chain! {
549+
foreign_links {
550+
Io(::std::io::Error);
551+
}
552+
}
553+
554+
fn run() -> Result<()> {
555+
let loopback = Ipv4Addr::new(127, 0, 0, 1);
556+
// Assigning port 0 requests the OS to assign a free port
557+
let socket = SocketAddrV4::new(loopback, 0);
558+
let listener = TcpListener::bind(socket)?;
559+
let port = listener.local_addr()?;
560+
println!("Listening on {}, access this port to end the program", port);
561+
let (mut tcp_stream, addr) = listener.accept()?; //block until requested
562+
println!("Connection received! {:?} is sending data.", addr);
563+
let mut input = String::new();
564+
// read from the socket until connection closed by client, discard byte count.
565+
let _ = tcp_stream.read_to_string(&mut input)?;
566+
println!("{:?} says {}", addr, input);
567+
Ok(())
568+
}
569+
570+
quick_main!(run);
571+
```
572+
573+
The `std` library is leveraged to make a well formed IP/port with the
574+
[`SocketAddrV4`] and [`Ipv4Addr`] structs. An unused random port is requested
575+
by passing 0 to [`TcpListener::bind`]. The assigned address is available via
576+
[`TcpListener::local_addr`].
577+
578+
[`TcpListener::accept`] synchronously waits for an incoming connection and
579+
returns a `(`[`TcpStream`], [`SocketAddrV4`]`)` representing the request.
580+
Reading on the socket with [`read_to_string`] will wait until the connection is
581+
closed which can be tested with `telnet ip port`. For example, if the program
582+
shows Listening on 127.0.0.1:11500, run
583+
584+
`telnet 127.0.0.1 11500`
585+
586+
After sending data in telnet press `ctrl-]` and type `quit`.
531587
<!-- Categories -->
532588

533589
[cat-encoding-badge]: https://img.shields.io/badge/-encoding-red.svg
@@ -543,6 +599,8 @@ fn run() -> Result<()> {
543599
[reqwest]: https://docs.rs/reqwest/
544600
[serde-badge]: https://img.shields.io/crates/v/serde.svg?label=serde
545601
[serde]: https://docs.rs/serde/
602+
[std]: https://doc.rust-lang.org/std
603+
[std-badge]: https://img.shields.io/badge/std-1.17.0-blue.svg
546604
[tempdir-badge]: https://img.shields.io/crates/v/tempdir.svg?label=tempdir
547605
[tempdir]: https://docs.rs/tempdir/
548606
[url-badge]: https://img.shields.io/crates/v/url.svg?label=url
@@ -573,3 +631,9 @@ fn run() -> Result<()> {
573631
[`serde_json::json!`]: https://docs.rs/serde_json/*/serde_json/macro.json.html
574632
[`TempDir::new`]: https://docs.rs/tempdir/*/tempdir/struct.TempDir.html#method.new
575633
[`TempDir::path`]: https://docs.rs/tempdir/*/tempdir/struct.TempDir.html#method.path
634+
[`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
635+
[`SocketAddrV4`]: https://doc.rust-lang.org/std/net/struct.SocketAddrV4.html
636+
[`TcpListener::accept`]: https://doc.rust-lang.org/std/net/struct.TcpListener.html#method.accept
637+
[`TcpListener::bind`]: https://doc.rust-lang.org/std/net/struct.TcpListener.html#method.bind
638+
[`TcpListener::local_addr`]: https://doc.rust-lang.org/std/net/struct.TcpListener.html#method.local_addr
639+
[`TcpStream`]: https://doc.rust-lang.org/std/net/struct.TcpStream.html

0 commit comments

Comments
 (0)