I am trying to understand asynchronous models in C++. I am investigating 4 libraries that purport to deal with asynchronous I/O:
liburing (C version, C++ version): provides an interface for io_uring. The C++ version uses coroutines.
libunifex: implements the C++ sender/receiver async programming model
Boost.Asio: library for asynchronous network and low-level I/O programming
CppCoro: provides a large set of general-purpose primitives for making use of coroutines
These libraries have an enormous amount of overlap.
Execution context and io_uring
The future of asynchronous I/O will likely use io_uring on Linux machines. liburing exists to provide an interface for io_uring with io_service. However, libunifex also provides io_uring_context. These both explicitly use io_uring but have usage similar to Boost.Asio's io_context and CppCoro's io_service.
Can liburing's io_service, libunifex's io_uring_context Boost.Asio's io_context, and CppCoro's io_service all be used together? If my code included all four of these libraries, would I have 1 execution context from each?
Functionality: opening files
This section contains an example of how CppCoro asynchronously opens a file. I believe this template class would be used in Boost.Asio for asynchronous file access. libunifex has an io_uring_text.cpp doc that includes asynchronous writes to files. Obviously liburing exists for asynchronously writing files.
Should I only use the io_uring specific libraries for file access?
Functionality: networking
Everyone knows that Boost.Asio provides networking functionality. CppCoro does too. The liburing GitHub includes an example echo server that uses low-level C code.
Linbunifex does not appear to include direct networking functionality. I presume it is meant to be combined with some other networking library. Would I combine it with one of the above three libraries to give an old library a sender-receiver interface? How would I do that?
Interface: coroutines
I'm guessing that coroutines are meant to be glue that allows these libraries to exist together. Boost.Asio is compatible with coroutines. liburing4cpp and libunifex have coroutine compatibility as a central feature. CppCoro, on the other hand, is essentially a coroutine library.
Does it at all make sense to talk about using coroutines as glue? Could I say "I will use library A to implement the async function and library B to handle the output of the async function"?
My Questions
Would you expect to see someone use all 4 of these libraries simultaneously? Are any of these libraries meant to be used on top of any of the others?
In cases where functionality overlaps, how do these libraries compare on performance? Is Boost.Asio falling behind new asynchronous models? Is Boost.Asio staying ahead by integrating the most recent asynchronous models? liburing4cpp included a low-level echo server that isn't much comparable to the modern interface of Boost.Asio. How do applications based on low-level io_uring usage compare to applications built using Boost.Asio?
I believe that senders/receivers in libunifex is primarily meant as an interface. Should I use it as an interface to other libraries, for example Boost.Asio?
Look at asio-grpc, I think they had almost all of your comparisons in examples
Related
I know that epoll and io_context work asynchronously. So, can you tell me what is the difference between the two?
Are you using epoll inside asio::io_context?
POSIX gives us a suite of utilities useful for dispatching on events and watching for activity on file descriptors. One of those utilities is epoll().
Boost ASIO also gives us a suite of utilities useful for dispatching on events and watching for activity on file descriptors. io_context is what it sounds like: a "handle" of sorts to a context for some I/O operations. Through an io_context you can poll() for activity (among other things).
They are two different interfaces for (in this comparison) a largely similar task. Boost ASIO, however, is an abstraction. Whether it uses epoll() under the bonnet to implement its magic is not really something we need to or should concern ourselves with, but it's certainly possible that it does so on POSIX systems. On Windows systems it would likely delegate to something else that the OS provides.
One school of thought is that cross-platform abstractions are always helpful, so the Boost ASIO technologies are a good choice for networking. On the other hand, some people find the old POSIX utilities to be simpler and more familiar to other programmers reading their code (as long as their target platforms support them); they also do not require you to ship a dependency. As with anything, it is up to you to decide which is the most appropriate for your use case and audience.
Node.js has a very good and well thought Net API.
I wonder is there a good C++ only implementation of that API as for example LuaNode do for Lua?
Take a look at node.native - attempt to implement api similar to node.js core lib, but with c++11 (and evented IO is also based on libuv)
There is nothing very similar that I know of.
However there are several reactor frameworks out there which give the same event queue driven environment. For example boost::asio provides an event queue that makes callbacks to handle network events, timers, and arbiatary events that you push onto the event queue.
It's largely the same idea, used in the same way. Howver it's nowhere near as simple as node.js to get started with, and does provide any non-blocking functions other than the basics I said above.
It does provide you with the environment to build your own system though. It's an excellent library, but probably rather lower level than you are looking for. There are other simiar libraries such as ACE and parts of the POCO c++ libraries too, but again, they are lower level than node.js with much less library support.
edit:
I've not looked at it too much but how about this https://github.com/joyent/libuv . This is a library that is used to implement some of the node.js features in a cross platform way. Maybe it's possible to use some of it for what you need?
Boost.Asio is conceptually very similar to Node.js. The primary difference being Asio is implemented as a library and Node.js is a language construct. Asio therefore exposes the event queue, requiring some initial setup to post callback handlers, and eventually a blocking call to start the event loop (io_service.run()).
If you're looking for a pure C++ API similar to Node.js, Boost.Asio is definitely the way to go. It is the de-facto networking library for many C++ applications. It's also discussed heavily on SO in the boost-asio tag.
I'm quite sure you could embed a Javascript engine into your program
v8 (building guide)
SpiderMonkey (building guide)
Actually tying that to your C code needs tinkering with the eval functions of both, but I think I remember seeing sample programs doing that for both engines
I am looking to write a server application in C++ that is meant to handle tens of thousands of clients simultaneously. It should run under Windows and Linux. I have been looking around for frameworks and libraries and have come across Boost Asio, which seems like a highly mature and widely used alternative. I just have trouble wrapping my head around strands/thread pools, mainly because of the millions of templates. My background is mainly in C, so am not really used to the template mess that Boost in general seems to be full of. I tried to find someone to develop a relatively thin wrapper around Boost Asio that would take care of the threading/synchronization aspect using strands, bind and the like, but have been unable to find someone yet who can do it within my budget (2 or 300 US dollars).
Can any of you recommend any other libraries that scale as well as Boost Asio (e.g. with IOCP on Windows and epoll on Linux etc), or a source where I might find skilled Boost developers looking for smaller freelance jobs?
Thanks very much in advance for any help.
Kind regards,
Philip Bennefall
Best 4 choices i know
I really like zeromq.. but libuv seems interesting.. (libev and libevent are very nice too)
zeromq
libevent (as said)
libev
libuv (Its purpose is to abstract
IOCP on windows and libev on Unix systems and it is node.js network layer)
ACE is the framework you are looking for. Even boost Asio is just an implementation of Proactor pattern, which was introduced by Douglas C. Schmidt. He is best known as the author of POSA Vol.2 and the creator of ACE framework.
The Boost.Asio library offers side-by-side support for synchronous
and asynchronous operations ... based on the Proactor design pattern
[POSA2].
Although it is a cross-platform C++ network framework and uses template,
just simple template is used. (or not at all)
My background is mainly in C, too, and I don't like Boost's massive template-programming style. However, ACE wasn't like that.
Try libevent on for size. Its whole raison d'etre is to address the C10K problem. I'd say it's probably more lightweight than boost.
Try Pulsar Server Framework. Main benefit is it is built over libuv network library (used by node.js) that uses asynchronous I/O based on event loops.
It’s perfectly scalable. You can just go adding servers as your user base increases.
It is designed to work with server farm.
Highly configurable and easy to use
Currently it has been built for Windows x64 server.
I have previously implemented server/client networking programs in C, but I have never done peer-to-peer program or any socket programming in C++.
For peer-to-peer, I guess I would have to create multiple threads and manage incoming and outgoing connections, since each program will work like a client and a server at the same time, right?
What would be a good way to implement this in C++? I believe C++ does not natively support threading...
You're not required to use multiple threads. An alternative is to use a single thread, and multiplex the sockets using select() (or poll() or epoll() or etc).
You might want to look into the boost.asio library which is good for multiple socket connctions (either threaded or not...)
Any code that would be valid in C is also valid in C++. So you can use the same socket API there and the same threading API (but the Boost wrappers might indeed be much more convenient).
Also C++ will natively support threading sometime towards the end of this year (the standard is already written and expected to be voted on by ISO later this year). Of course it may take some time to show up in your compiler/stdlibc++ (but gcc/gnu stdlibc++ already implements it except for language support for thread-local storage (which it does support, but using the older compiler-specific way)). For compilers that don't support it, the boost version is mostly compatible to the proposed standard anyway.
I really thought this would be easier to find...
I need a portable c++ sockets wrapper. I'm planning to use it for a windows server application and a client that will be running on a embedded device running ulinux (or something similar). I would use Boost but I need it to be lightweight and easy to add to the embedded device project.
Also I would like it to be a "higher level" wrapper... so it starts a background thread to read data and informs be over a callback...
Any ideas?
I'd suggest Boost.Asio. Despite it's name, you are not forced to use asynchronous I/O. You could use synchronous I/O and threads, as your question implies.
Boost.Asio is a cross-platform C++
library for network and low-level I/O
programming that provides developers
with a consistent asynchronous model
using a modern C++ approach.
Just learn to use the socket API directly. You can then easily wrap it yourself. It's not that hard, and you can get started with Beej's excellent guide. As Beej says:
The sockets API, though started by the
Berkeley folk, has been ported to many
many platforms, including Unix, Linux,
and even Windows.
In his guide he details the very small addition you need to do to get the same API in Windows and *nix systems.
Once you've learned, wrap it yourself if you're so inclined. Then you can control exactly how "lightweight" you want it.
If you really don't like Boost asio then you might like the sockets support in dlib. It is simpler in the sense that it uses traditional blocking IO and threads rather than asio's asynchronous proactor pattern. For example, it makes it easy to make a threaded TCP server that reads and writes from the iostreams. See this example for instance. Or you can just make a simple iosockstream if not acting as a server.
I know this is old, but there is a very nice and simple implementation in below location which I'm using for personal use. Had implemented my own wrapper a while back but lost the code and found this one online which is much better than mine:
http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/
Take a look at ENet http://enet.bespin.org/ it is very lightweight and portable and works on top of UDP, with optional support for reliable packets. It is easy to use, the API is low-level and with little performance overhead. You have a high degree of control over the memory management, which could be good if networking is a bottleneck for you and the malloc/new implementation you use performs badly under multithreading.
It would not be that hard to implement your high level thread “optimally”, since there is optional support for blocking receive and the library is a “library” and not a framework therefore you are the decision maker instead of the library.
Perhaps you can have a look at http://www.pt-framework.org/
Old question, but for C++, BSD style synchronous sockets this is about as minimal baggage wrapper as you can find
http://code.google.com/p/ting/source/browse/trunk/src/ting/net/
It does come with exceptions. You could make a bit more lightweight one as a header-only template library, and maybe make exceptions optional, but that would change the API a bit
POCO network classes are quite similar, but do require more dependencies from other parts of the Poco lib
I'm personally creating my own AsIO wrapper for both TCP and Serial sockets, and I started by reviewing the following tutorial:
https://www.gamedev.net/blogs/blog/950-they-dont-teach-this-stuff-in-school/
and
https://objectcomputing.com/resources/publications/mnb/multi-platform-serial-interfacing-using-boost-a-gps-sensor-and-opendds-part-i/
I found the first one very useful and simple to understand.
C++CSP2
Used it loved it. Stable and powerful