Skip to content

acikgozb/beej-net-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bjrs

This repository contains the Rust rewrites of examples that are explained in Beej's Guide to Network Programming.

Table of Contents

Requirements

The Rust toolchain needs to be installed on the host to run the examples. It can be installed from here.

Implementation

I tried to keep the examples as close to the original implementations as possible, therefore the project only uses the libc crate for each example. As a result, unsafe blocks are heavily used throughout the project.

The only exception to this decision is the C examples of pollserver and selectserver. These examples do more unsafe operations than the underlying syscalls that are basically not accepted by safe Rust (e.g. mutating a collection while traversing). Therefore, in order to keep unsafe blocks under control, additional structures are used for these, which made them a bit more verbose compared to their C counterparts.

Usage

Some examples can be run standalone, but some require multiple shell sessions. Before running the examples, I would recommend to check out the long help text first.

$ cargo run -- --help
# Usage: bjrs <COMMAND>
#                                                                                                                                                                             
# Commands:
#   syscall     Chapter 5 - System Calls or Bust
#   stream      Section 6.1 & 6.2 - A Simple Stream Server & Client
#   dgram       Section 6.3 - Datagram Sockets
#   techniques  Chapter 7 - Slightly Advanced Techniques
#   help        Print this message or the help of the given subcommand(s)
#                                                                                                                                                                             
# Options:
#   -h, --help     Print help
#   -V, --version  Print version
$ cargo run -- syscall --help
# Chapter 5 - System Calls or Bust
#                                                                                                                                                                             
# Usage: bjrs syscall <COMMAND>
#                                                                                                                                                                             
# Commands:
#   getaddrinfo  Section 5.1 - `getaddrinfo()` - Prepare to Launch!
#   socket       Section 5.2 - `socket()` - Get the File Descriptor!
#   bind         Section 5.3 - `bind()` - What Port Am I On?
#   connect      Section 5.4 - `connect()` - Hey, you!
#   listen       Section 5.5 - `listen()` - Will Somebody Please Call Me?
#   accept       Section 5.6 - `accept()` - "Thank you for calling port 3490."
#   send         Section 5.7 - `send() and recv()` - Talk to me, baby!
#   recv         Section 5.7 - `send() and recv()` - Talk to me, baby!
#   sendto       Section 5.8 - `sendto() and recvfrom()` - Talk to me, DGRAM-style
#   recvfrom     Section 5.8 - `sendto() and recvfrom()` - Talk to me, DGRAM-style
#   close        Section 5.9 - `close() and shutdown()` - Get outta my face!
#   shutdown     Section 5.9 - `close() and shutdown()` - Get outta my face!
#   getpeername  Section 5.10 - `getpeername()` - Who are you?
#   gethostname  Section 5.11 - `gethostname()` - Who am I?
#   help         Print this message or the help of the given subcommand(s)
#                                                                                                                                                                             
# Options:
#   -h, --help  Print help

Here is an example where it needs manual preparation:

$ cargo run -- stream server --help
# Section 6.1 - A Simple Stream Server
#                                                                                                                                                                             
# To test this example:
#                                                                                                                                                                             
# Run this command to start our "TCP" server. In a separate terminal session, run the client command `bjrs stream client`. Observe that the server sends the message "Hello world!" to the client.
#                                                                                                                                                                             
# Usage: bjrs stream server
#                                                                                                                                                                             
# Options:
#   -h, --help
#           Print help (see a summary with '-h')

Examples

Some examples in Beej's book are in their own C files and some of them are inlined to .md pages.

Here is how the examples in this project are mapped to Beej's book. The inlined examples are shown with md prefix, and C files are shown as is:

Section 5.1 - getaddrinfo() - Prepare to Launch!

showip.c -> getaddrinfo.rs

Section 5.2 - socket() - Get the File Descriptor!

For socket(), Beej shows the usage via a pseudocode. In here, I tried to build on getaddrinfo() to showcase how a basic socket() call can be made.

md-socket -> socket.rs

Section 5.3 - bind() - What Port Am I On?

md-bind -> bind.rs (fn bind)

md-bind-port-reuse -> bind.rs (fn reuse_port)

Section 5.4 - connect() - Hey, you!

md-connect -> connect.rs

Section 5.5 - listen() - Will Somebody Please Call Me?

md-listen -> listen.rs

Section 5.6 - accept() - "Thank you for calling port 3490."

md-accept -> accept.rs

Section 5.7 - send() and recv() - Talk to me, baby!

md-send -> send.rs

md-recv-synopsis -> recv.rs

Section 5.8 - sendto() and recvfrom() - Talk to me, DGRAM-style

md-sendto-synopsis -> sendto.rs

md-recvfrom-synopsis -> recvfrom.rs

Section 5.9 - close() and shutdown() - Get outta my face!

md-close-synopsis -> close.rs

md-shutdown-synopsis -> shutdown.rs

Section 5.10 - getpeername() - Who are you?

md-getpeername-synopsis -> getpeername.rs

Section 5.11 - gethostname() - Who am I?

md-gethostname-synopsis -> gethostname.rs

Section 6.1 & 6.2 - A Simple Stream Server & Client

server.c -> server.rs

client.c -> client.rs

Section 6.3 - Datagram Sockets

listener.c -> server.rs

talker.c -> client.rs

Section 7.1 - Blocking

md-blocking -> blocking.rs

Section 7.2 - poll() - Synchronous I/O Multiplexing

poll.c -> poll.rs

pollserver.c -> pollserver.rs

Section 7.3 - select() - Synchronous I/O Multiplexing, Old School

select.c -> select.rs

selectserver.c -> selectserver.rs

Section 7.7 - Broadcast Packets - Hello, World!

broadcaster.c -> broadcaster.rs

Notes

If you check the very first example and compare it to the last ones, you will see that there are quite a bit differences regarding how the unsafe operations are executed, such as:

  • The contents of unsafe blocks,
  • The contents of SAFETY comments,
  • The countless casts done between pointers and types themselves.

This results in an inconsistency between the examples, and I intentionally kept this fact. It shows how unsafe Rust effects the thought process the more you write, which is pleasant to reveal.

LICENSE

This work is dual-licensed under Apache 2.0 and GPL 2.0 (or any later version). You can choose between one of them if you use this work.

SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later

About

Examples of Beej's Guide to Network Programming, from C to Rust.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages