# Network Programming With Rust ![rw-book-cover](https://m.media-amazon.com/images/I/81JaVYnfMiL._SY160.jpg) ## Metadata - Author: James L. Reid - Full Title: Network Programming With Rust - Category: #books ## Highlights - Protocols define how data is structured, addressed, transmitted, received, and potentially even corrected for errors. ([Location 262](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=262)) - Two of the most fundamental protocols in networking are TCP (Transmission Control Protocol) and UDP (User Datagram Protocol). ([Location 267](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=267)) - TCP: The Reliable Conversationalist: TCP is like a formal conversation where each message is acknowledged and re-transmitted if it gets lost. ([Location 269](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=269)) - UDP: The Speedy Messenger: UDP is like a quick, casual chat where messages are sent without waiting for confirmation. ([Location 273](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=273)) - IP Address: A unique numerical label assigned to each device connected to a network. ([Location 298](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=298)) - Port: A communication endpoint within a device, identified by a number. Different ports are used for different services (e.g., port 80 for HTTP web traffic). ([Location 300](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=300)) - Socket: An endpoint of a two-way communication link between two programs running on a network. ([Location 302](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=302)) - Client: A program that requests a service from a server. ([Location 303](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=303)) - Server: A program that provides a service to clients. ([Location 305](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=305)) - Rust is a statically-typed language, meaning that the data type of a variable is determined at compile time and cannot be changed later. ([Location 581](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=581)) - Each module can have its own functions, data types, and even sub-modules. ([Location 624](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=624)) - Single Responsibility: Only the owner of a value can modify or destroy it. This avoids conflicts where multiple parts of your code try to manipulate the same data simultaneously. ([Location 781](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=781)) - Clear Lifecycle: When the owner goes out of scope (like a guest leaving the potluck), the value is automatically dropped, and its memory is freed. This eliminates the need for manual memory management and prevents leaks. ([Location 783](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=783)) - Move Semantics: When you assign a value to a new variable, the ownership is transferred, and the original variable becomes invalid. This prevents the creation of dangling pointers that could lead to undefined behavior. ([Location 786](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=786)) - Immutable Borrows (&T): The borrower can only read the value, not modify it. This ensures that the owner can continue to use the value safely. ([Location 810](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=810)) - Mutable Borrows (&mut T): The borrower can modify the value. However, only one mutable borrow is allowed at a time, preventing data races. ([Location 813](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=813)) - Borrowing is not unlimited. Each borrow has a lifetime, which is the scope for which the borrow is valid. ([Location 851](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=851)) - In network programming, you often deal with data that's shared across different threads or even different machines. Ownership and borrowing help you ensure that this data is accessed safely and consistently, preventing errors like data races, memory leaks, and dangling pointers. ([Location 872](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=872)) - Pattern Matching (match): This is the most flexible and powerful way to handle Result values. It allows you to write code that branches based on whether the result is Ok or Err. ([Location 912](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=912)) - Unwrapping (unwrap): This is a shortcut that extracts the value from an Ok result or panics (crashes your program) if the result is Err. Use this only if you're absolutely sure the result will be Ok. ([Location 931](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=931)) - Error Propagation (?): This operator is a convenient way to propagate errors up the call stack. If the result is Err, the error is returned from the current function; otherwise, the value is unwrapped and used. ([Location 941](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=941)) - Remember, errors are a natural part of programming, and handling them gracefully is essential for building reliable and robust network applications. ([Location 1041](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1041)) - A thread is a sequence of instructions that can be executed independently of other threads within the same program. ([Location 1054](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1054)) - Message passing is a way for threads to communicate with each other by sending and receiving messages. ([Location 1062](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1062)) - Asynchronous programming is a way to write code that can perform multiple operations concurrently without blocking the main thread. ([Location 1088](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1088)) - Tokio: The Async Powerhouse At the heart of many Rust network applications lies Tokio, a blazing-fast asynchronous runtime. ([Location 1147](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1147)) - Tokio provides the foundation for building asynchronous network applications in Rust. It handles tasks like scheduling, managing event loops, and executing asynchronous operations concurrently. ([Location 1151](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1151)) - The HTTP Maestro Hyper is a high-performance HTTP library that specializes in crafting and serving web traffic. ([Location 1156](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1156)) - Reqwest: Your HTTP Messenger Reqwest is a user-friendly HTTP client library, designed to simplify the process of sending HTTP requests and receiving responses. ([Location 1164](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1164)) - Mio: The I/O Virtuoso Mio is a low-level I/O (Input/Output) library that acts as the foundation for many higher-level network libraries, including Tokio. ([Location 1173](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1173)) - Serde: The Data Transformer Serde is a powerful framework for serializing and deserializing Rust data structures. ([Location 1181](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1181)) - A trait is essentially a collection of method signatures (names and parameters) without their implementations. It's like a checklist of behaviors that a type must fulfill to be considered part of that trait "club." ([Location 1226](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1226)) - To use a trait, you need to implement it for specific types. This is where you provide the actual code that defines how the type will behave for each method in the trait. ([Location 1249](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1249)) - Traits enable a powerful concept called polymorphism. This means you can write code that works with any type that implements a particular trait, without needing to know the specific type at compile time. It's like having a generic animal feeder that can dispense food to any animal, regardless of whether it's a lion or a giraffe. ([Location 1283](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1283)) - The AsyncRead and AsyncWrite traits provide asynchronous versions of Read and Write, enabling efficient, non-blocking I/O operations. These traits are essential for building high-performance network servers and clients. ([Location 1313](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1313)) - Traits define shared behaviors that types can implement. Implementing a trait means providing the specific code for each method in the trait. Traits enable polymorphism and generic programming, allowing you to write more flexible and reusable code. Traits are essential for abstracting over different types of network connections, protocols, and data formats in Rust network libraries. ([Location 1324](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1324)) - Open Systems Interconnection (OSI) model, a conceptual framework that divides network communication into seven distinct layers. ([Location 1370](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1370)) - Layer 1: Physical Layer This is the foundation of the building, representing the physical hardware used for communication. It deals with the raw transmission of bits over a medium like copper wires, fiber optic cables, or radio waves. ([Location 1375](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1375)) - Layer 2: Data Link Layer As we move up to the second floor, we encounter the data link layer, responsible for establishing and maintaining reliable links between network devices. It ensures that data is transmitted accurately and efficiently within a single network segment. ([Location 1378](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1378)) - Layer 3: Network Layer On the third floor, we find the network layer, which handles routing and addressing. It determines the best path for data to travel across multiple networks to reach its destination. ([Location 1382](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1382)) - Layer 4: Transport Layer The fourth floor houses the transport layer, which ensures reliable delivery of data between applications running on different devices. It divides data into smaller chunks called segments or datagrams, adds error-checking mechanisms, and reassembles the data at the receiving end. ([Location 1385](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1385)) - Layer 5: Session Layer As we ascend to the fifth floor, we enter the session layer, which manages the establishment, coordination, and termination of connections between applications. ([Location 1389](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1389)) - Layer 6: Presentation Layer On the sixth floor, we find the presentation layer, which transforms data into a format that the application layer can understand. It handles tasks like encryption, decryption, compression, and decompression. ([Location 1392](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1392)) - Layer 7: Application Layer Finally, we reach the top floor, the application layer, where network applications interact with users and exchange data. This is where you'll find familiar protocols like HTTP for web browsing, SMTP for email, and FTP for file transfer. ([Location 1396](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1396)) - The OSI model provides a standardized framework for understanding and troubleshooting network communication. It breaks down complex processes into manageable layers, allowing you to pinpoint issues at specific levels. ([Location 1433](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1433)) - Design network applications: You'll be able to choose the right protocols and technologies for each layer, ensuring optimal performance and reliability. ([Location 1435](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1435)) - Troubleshoot network problems: You'll be able to isolate issues at specific layers, making it easier to identify and fix problems. ([Location 1437](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1437)) - Communicate with other network professionals: You'll have a common language to discuss network concepts and issues, facilitating collaboration and knowledge sharing. ([Location 1439](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1439)) - TCP is the protocol of choice for applications that demand reliability and accuracy. It establishes a connection between the sender and receiver before any data is transmitted, like a phone call where you first dial the number and wait for the other person to pick up. Once the connection is established, TCP ensures that every packet of data is delivered in the correct order and without errors. ([Location 1454](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1454)) - Handshake: Before any data is sent, the sender and receiver perform a three-way handshake to establish a connection. This involves exchanging SYN (synchronize) and ACK (acknowledgement) packets to confirm that both parties are ready to communicate. ([Location 1458](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1458)) - Sequence Numbers: Each packet of data is assigned a unique sequence number. ([Location 1461](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1461)) - Acknowledgements: The receiver sends back an ACK packet to confirm that it has received each packet. ([Location 1463](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1463)) - Flow Control: TCP also uses flow control to prevent the sender from overwhelming the receiver with data. ([Location 1465](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1465)) - Congestion Control: In addition to flow control, TCP also uses congestion control to manage network congestion. ([Location 1467](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1467)) - UDP, the protocol designed for speed. Unlike TCP, UDP is connectionless, meaning that it doesn't establish a connection before sending data. It simply sends packets of data without any guarantee of delivery or order. ([Location 1473](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1473)) - A socket is a software abstraction that represents an endpoint of a network communication link. ([Location 1521](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1521)) - A socket is created by a process (a running program) using the socket API (Application Programming Interface) provided by the operating system. The API provides functions for creating, connecting, sending, and receiving data through sockets. ([Location 1526](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1526)) - Stream Sockets (TCP): These sockets provide a reliable, ordered, and byte-oriented communication channel. They're suitable for applications that require data to be transmitted without errors and in the correct order, such as web browsing, email, and file transfer. ([Location 1534](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1534)) - Datagram Sockets (UDP): These sockets provide a connectionless, unreliable, and message-oriented communication channel. They're faster than stream sockets but don't guarantee delivery or order. ([Location 1537](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1537)) - Sockets are often used in a client-server model, where one process acts as the server and listens for incoming connections, while other processes act as clients and initiate connections to the server. ([Location 1562](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1562)) - Rust provides a rich set of tools for working with sockets. The standard library's std::net module provides types like TcpStream, TcpListener, UdpSocket, and more. Additionally, crates like tokio and mio offer powerful abstractions for building asynchronous and high-performance network applications. ([Location 1573](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1573)) - IPv4: This is the older and more widely used format, consisting of four numbers separated by dots (e.g., 192.168.1.100). IPv4 addresses are 32 bits long, allowing for a maximum of roughly 4.3 billion unique addresses. ([Location 1592](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1592)) - IPv6: This is the newer format, designed to address the increasing demand for IP addresses. IPv6 addresses are 128 bits long, allowing for a virtually unlimited number of unique addresses. ([Location 1594](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1594)) - In the realm of network programming, things rarely go exactly as planned. Networks are inherently unreliable, with connections dropping, packets getting lost, and servers occasionally misbehaving. Errors are simply a fact of life in this environment. ([Location 1950](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=1950)) - You can use the ? operator to propagate these errors up the call stack or use match to handle them in a more specific way. ([Location 2047](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2047)) - In this pattern, multiple threads share access to the same data, but a mutex (mutual exclusion) lock is used to ensure that only one thread can access the data at a time. ([Location 2132](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2132)) - We use Arc (Atomic Reference Counting) to create a thread-safe reference to the counter that can be shared across multiple threads. ([Location 2193](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2193)) - We use Mutex to create a lock around the counter, ensuring that only one thread can access it at a time. ([Location 2195](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2195)) - If you have a large number of short-lived connections and need maximum isolation between clients, the thread-per-connection pattern might be a good choice. ([Location 2201](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2201)) - If you have a smaller number of long-lived connections and need to share data between them, the shared state with mutexes pattern might be more suitable. ([Location 2203](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2203)) - In Rust, an asynchronous task is represented by a Future, which is a value that represents an eventual result. Futures can be combined, chained, and manipulated in various ways, allowing you to build complex asynchronous workflows. ([Location 2314](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2314)) - futures don't execute themselves. They need a runtime to drive their execution. That's where Tokio comes in. ([Location 2317](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2317)) - Reactor: The reactor is the heart of the runtime. It listens for events (like incoming network connections or completed I/O operations) and dispatches them to the appropriate tasks. ([Location 2322](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2322)) - Executor: The executor is responsible for running the tasks. It maintains a queue of tasks that are ready to be executed and uses a scheduling algorithm to determine the order in which they should run. ([Location 2325](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2325)) - Timer: The timer allows you to schedule tasks to be executed at a specific time or after a certain delay. ([Location 2327](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2327)) - I/O Driver: The I/O driver handles the low-level details of interacting with the operating system's I/O mechanisms. ([Location 2330](https://readwise.io/to_kindle?action=open&asin=B0D8GP6131&location=2330))