Have you ever thought about how we can send and receive messages in the application? Do you know Asio library provides Asio Channels which, helps to achieve this?
In this article, we will discuss Asio channels. We will discuss few member functions that can be used in Asio Channels. We will understand these member functions with the help of an example. Moving forward, let’s first understand a bit about the Asio library.
What is Asio?
Asio stands for Asynchronous Input Output. Asio is a C++ library that allows processing data asynchronously. It provides asynchronous models with the latest C++ approach and basic building blocks for C++ networking and concurrency. Asio is a low-level input-output programming. Before moving further, let’s first understand how we can run our programs using the Asio library. Asio library is useful as it allows network programming in C++.
Setting Up Asio
For executing programs using the Asio library, we must need Visual Studio, while installing visual studio, select Desktop environment for C/C++. After that, we must download Asio C++ Library. After downloading both Visual Studio and Asio C++ Library, follow the below steps to set up the project using Asio on visual studio.
Create an empty project on visual studio.
2. Once the project is created, right-click on Source Files -> Add -> New Item.
3. Create a file with a .cpp extension.
4. To include the Asio library, right-click on Project name -> properties. Select C/C++ Configuration.
5. In Additional Include Directories, add the path till Asio include folder. For example, in our case the path is
Channels are C++ template library which helps in passing messages. In Asio library, there are channels that allow sending and receiving messages bidirectionally in the application. These messages are a set of arguments that has to be passed to a completion handler. These messages can be sent and received either by asynchronous operations or by non-blocking synchronous operations. Moving forward, let’s discuss basic_channels and basic_concurrent_channels.
The basic_channelclass is used for sending a set of arguments to a completion handler. For using the basic_channels class, we must include the asio/experimental/basic_concurrent_channel.hpp header in our program. The basic_channel class is not thread-safe. The basic_concurrent_channel can be used for passing messages for the code that is running in different threads.
For using basic_concurrent_channel, we must include the asio/experimental/basic_concurrent_channel.hppheader.
There are certain member functions that can be used in Asio Channels:
👉 async_receive is used for receiving a message asynchronously.
👉 async_send is used for sending a message asynchronously.
👉 cancel function is used for canceling all the asynchronous operations that are waiting on the channel.
👉 capacity gets the buffer capacity of the channel
There are a few more functions like try_receive, try_send, and try_send_n which are used for trying to receive, send and send a number of messages non-blocking.
Let’s understand Asio Channels with the help of an example by using few member functions.
To execute programs using Asio Channels, your C++ language standard option must be set as ISO C++20 Standard (/std:c++20). To set this, follow the below-mentioned steps:
After you have created your empty project in visual studio, right-click on project name -> Properties -> C/C++ Configuration -> All options -> C++ Language Standard and select C++20 Standard (/std:c++20) from the drop-down.
Now, you are good to use Asio Channel functions.
Code
#include <iostream>
#include <asio.hpp>
#include <asio/experimental/awaitable_operators.hpp>
#include <asio/experimental/channel.hpp>
#include <asio/error_code.hpp>
#include "asio/experimental/basic_channel.hpp"
using namespace std;
using namespace asio::experimental::awaitable_operators;
using channel_t = asio::experimental::channel< void(error_code, uint64_t) >;
asio::awaitable< void >
ninja(channel_t& ch)
{
std::cout << "Entered ninja Channel" << endl;
for (uint64_t i = 0; i < 10; i++)
co_await ch.async_send(error_code{}, i, asio::use_awaitable);
std::cout << "Printing Executor ";
std::cout << ch.get_executor() << endl;
std::cout << "ninja Channel is opened so is_open() function is returning ";
std::cout << ch.is_open() << endl;
std::cout << "Checking whether a message can be received without blocking or not using ready() function ";
std::cout << ch.ready() << endl;
std::cout << "Checking buffer capacity of ninja channel using capacity() function ";
std::cout << ch.capacity() << endl;
ch.close();
std::cout << "Closing ninja Channel..." <<endl;
std::cout << "ninja Channel is closed so is_open() function is returning ";
std::cout << ch.is_open() << endl;
}
asio::awaitable< void >
enter()
{
channel_t ch{ co_await asio::this_coro::executor, 10 };
co_await(ninja(ch));
}
int main()
{
asio::io_context io{};
std::cout << "Checking whether Asio Channels are working fine or not" << endl;
asio::co_spawn(io, enter(), asio::detached);
io.run();
std::cout << "Working Fine..." << endl;
}
Explanation
In the above code, we are making two channels named enter and ninja. In the main function co_spawn function is called with three arguments that are context, enter channel, and a completion token detached. The completion tokenhelps in producing a completion handler, here we are using detached() as a completion token which is used to indicate the detached asynchronous operations. In the ninja channel, we have used the asyn_send function, which is used to send messages asynchronously. We have used and printed the results of functions get_executor(), is_open(), ready(), capacity(), and close() to understand them clearly.
The basic_channel class is used for sending messages across different parts of the same application.
What is the difference between basic_channel and basic_concurrent_channel?
The basic_channel is not thread-safe, so it can be run in a single thread, whereas basic_concurrent_channel is thread-safe and can be run on different threads.
What is the use of the reset function?
The reset function is used to reset the channel to its initial state.
What functions can be used for sending and receiving messages without blocking?
The try_sendfunction is used to send messages non-blocking, whereas the try_receive function is used to receive messages non-blocking.
Conclusion
In this article, we have discussed Asio channels. We have seen how we can set up the Asio library in our machine for programming. We have discussed basic_channel and basis_concurrent_channel and their member functions that can be used. To know more about the Asio library, you can read the below-mentioned articles:
I hope this article has helped you in understanding a bit more about Asio library. If this article helped you in any way, then you can read more such articles on our platform, Coding Ninjas Studio. You will find articles on almost every topic on our platform. Also, for cracking good product-based companies, you can practice coding questions at Coding Ninjas. For interview preparations, you can read the Interview Experiences of popular companies.