Networking in C++ with ASIO: Building a Client-Server Framework (Part 1)
0:03 Introduction to using ASIO (Asynchronous Input/Output) for networking in C++, aiming to develop a framework for server-client communication.
0:18 Sockets can be fiddly and tricky to work with because they're platform dependent.
0:50 Tradition networking in C++ is tricky due to the lack of standardization, but libraries like ASIO improve portability. The channel will be developing its custom framework.
1:16 ASIO is written in modern C++, and the series will explain each line of code for educational purposes.
1:53 Part one covers acquiring and installing ASIO, basic examples in a non-asynchronous manner, problems with networking, the overall framework architecture, and development of critical building blocks.
2:24 Downloading ASIO from think-async.com; ASIO originated in Boost but can be used standalone.
2:58 ASIO is header-based, requiring no libraries to link. Install by extracting the folder into the SDK directory.
3:12 Create a Visual Studio project and link to the ASIO header files in project properties.
3:15 Core ASIO functionality requires including asio.hpp.
3:31 Additional header files buffer and internet are included for memory management and network communication.
3:46 Define WIN32_WINNT on Windows to specify the Windows version for networking.
3:58 Focus is on shifting data between computers, not low-level network details.
4:05 ASIO handles errors well using asio::error_code.
4:15 ASIO requires an asio::io_context for performing operations, hiding platform-specific details.
4:31 Construct a tcp::endpoint with an IP address and port using make_address.
4:48 Create a tcp::socket and associate it with the io_context.
4:54 Attempt to connect to the specified address using socket.connect.
5:12 If connection was successful, then the code determines if the socket is_open().
5:15 Sends an HTTP request string to the server using socket.write_some via an ASIO buffer.
5:31 Check if there are bytes available to read using socket.available, then read into a vector with socket.read_some.
5:57 Illustrates a common problem: programs immediately trying to read the response are prone to failure, because the network takes time.
6:15 Explores use of hard-coded delays to solve the problem.
6:51 Demonstrates potential solutions, such as the use of the socket.wait() function.
7:15 The channel then shows the user another problem when connecting to sites that require a large amount of data: using asynchronous programming.
7:43 Shows how the use of the asyncreadsum function addresses this problem.
8:11 Demonstrates how to create prime ASIO to read data and display it to the console using lambda functions and a large buffer, which makes asio run in the background.
8:55 Demonstrates code being called again recursively until there's no data left to read.
9:44 The overall problem is that asynchronous behavior isn't going to happen when you expect it. The idea of preparing to do work involving variables such as time delays and buffers is powerful.
10:09 The custom framework needs to provide tools and utilities that are flexible enough to provide message passing between client and server.
10:33 Our data transactions are going to involve messages, and the messages are going to have two components, namely a header and body.
10:38 The message header is going to consist of an identifier and the size of the message. The message body is going to consist of the message payload.
11:05 This means we're never going to be transmitting data of an unknown size.
11:11 Instead of an integer id, the channel intends to specify an enum class, so the compiler can identify if invalid ids are used.
11:40 I can't go and provide an enum class filled with millions of different types of messages.
11:46 User specifies their own enum class. The framework will template to customize messages.
11:54 Message is going to serialize and deserialize data, making it easier to use. By doing it this way, client and server interfaces don't need to be modified by the user.
12:08 Add static library project named net common. Delete junk.
12:24 Create net common.h to include commonly used standard files and ASIO.
12:32 Create netmessage.h and include definition of message object.
12:45 The framework is header only. Create namespaces olc::net.
12:57 Define a structure that represents the message header, using the template keyword.
13:20 Deliberately not using size_t because it might be different between 32-bit and 64-bit systems.
13:35 It's important that byte order is the same between server and client.
13:38 The message itself needs to rely on a message header template.
13:59 Add the vector body, using std::vector<uint8_t>.