7 ms·
Dalin – A C++ non-blocking network library on Linux
- jitl 9y agoIt would be great if there was an obvious example of some sort in the README. I really have no idea what this offers other than “Linux-only” and “async”
- fsloth 9y ago"Only runs on Linux" C/C++ doesn't really have good general networking libraries that fit all purposes. On that note, I say: yes, great topic! However. Portability is one of the key features of C++, and why people still choose it for new projects. If one can constrain project to Linux I'm sure the project constraints would allow a more productive language to be used altogether.
- loxias 9y agoOn the one hand, you're right -- in that I can see and respect why you say that. On the otherhand, what the heck is wrong with using the syscalls? Every time I write a new high performance networking application, sure, i lose a day or two building primitives out of send recvmsg listen accept and splice, but once i'm done, i'm done, and things work. I'm confused why people feel the need to make paper thin abstraction layers covering the berkeley sockets API. In the time it takes one to learn how to use the flavor of the month, one probably has gotten halfway there to understanding how to Really do networking. It's not like networking on Linux is even a shred harder than easy...mumbles off into the distance unlike BLE on Windows10 (and linux).... Tangentially, I positively can't WAIT for Networking support in c++20 -- that and Concepts I've been waiting for with baited breath. [EDIT: apologies, i think my tone got away with me.. stupid aspie tendencies... what i MEANT to say somewhere in there, directed to the author, was: "Good Job!!" It's hard work to put yourself out there and enjoy accomplishment. Please do let the rest of the community know if you'd welcome help in porting it to other platforms and adding features and improving performance. Best!]
- moron4hire 9y agoBLE on Windows 10 is exactly the same as BLE on every other platform.
- jcelerier 9y agoWhat ? of course not. The BLE (and bluetooth, for what it's worth) API is different on every platform. On windows: https://msdn.microsoft.com/en-us/library/windows/hardware/hh450825(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/hardware/hh... On linux: https://github.com/carsonmcdonald/bluez-experiments/blob/master/experiments/scantest.c https://github.com/carsonmcdonald/bluez-experiments/blob/mas... On macOS: https://github.com/sandeepmistry/osx-ble-peripheral/blob/master/BLEPeripheral/BPAppDelegate.m https://github.com/sandeepmistry/osx-ble-peripheral/blob/mas...
- moron4hire 9y agoThe names of the functions are different, but they fundamentally do the same things
- juiyout 9y agoIsn't every platform "fundamentally" do the same things?
- jcelerier 9y ago> On the one hand, you're right -- in that I can see and respect why you say that. > On the otherhand, what the heck is wrong with using the syscalls? Every time I write a new high performance networking application, sure, i lose a day or two building primitives out of send recvmsg listen accept and splice, but once i'm done, i'm done, and things work. ... > Tangentially, I positively can't WAIT for Networking support in c++20 -- that and Concepts I've been waiting for with baited breath. You know that the networking support in c++20 is just Boost.Asio with namespace std, right ? You could have been using the exact same API today (or ten years ago for what it's worth), which is header-only, and supports TCP, UDP, Unix sockets, SSL, serial port communication, and all of this either synchronously or asynchronously, etc... > I'm confused why people feel the need to make paper thin abstraction layers covering the berkeley sockets API. Because: * there are more efficient ways than the sockets API. For instance on windows the preferred way is IOCP: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa3... which allows for far better behaviour when multi-threading than select / poll. * that's like saying "std:string is a thin abstraction layer over const char* and strlen". There is much more to this in big networking libraries: event loop handling, thread pools, etc.
- inetknght 9y agoHow does this differ from, eg, asio?
- loxias 9y ago"asio requires boost"
- alexott 9y agoNot necessary to pull whole boost
- deleted 9y ago[deleted]
- eps 9y agoYou are missing gp's point. Any boost dependency is an instant no-go in a lot of projects.
- beojan 9y agoASIO doesn't require boost, there's a stand-alone version.
- felixguendling 9y agoAsio is also available as a standalone library without any dependencies (C++11): https://think-async.com/ https://think-async.com/
- arunc 9y agoWhy is that? Most of the modern c++ features were directly borrowed from boost
- whatidonteven 9y agoCompile time is a pretty big reason.
- bullen 9y agoCan you make a small web server on top of this to demonstrate the performance?
- naturalgradient 9y agoWhy is it not using C++ 14? Not a criticism, honest question, I only write C++ occasionally.
- fnj 9y agoIt's not even fully C++11. Massive fail.
- naturalgradient 9y agoWhy is this being downvoted? I don't know why one would prefer either.
- johannes1234321 9y agoFrom a short review I don't like this much. - It's containing it's own abstraction over pthread instead of std::thread/std::mutex/... - It passes shared_ptr via reference (yeah, this saves an increment and decrement on the refcounting, but the code is not tuned that much) - it prints directly to sterr (via fprintf) making it hard to redirect errors somewhere else - It seems not to be prepared to be ported to other platforms - It could make use of std::chrono instead of int64 timestamps - no build system (no CMake or anything) - tests not integrated, look verbose, all tests individually recompile all files, makes it hard to work test-drive In summary I see no compelling reason over boost asio or such and potential issues.
- fnj 9y ago> It passes shared_ptr via reference Talk about not getting it.
- sb10128 9y agoCan you explain what you mean here? Isn't what the op is doing generally ok - to pass shared_ptr's by const reference to save an additional increment/decrement on function call? https://stackoverflow.com/questions/3310737/shared-ptr-by-reference-or-by-value https://stackoverflow.com/questions/3310737/shared-ptr-by-re...
- banachtarski 9y agoIt isn't idiomatic. If you've already locked the shared_ptr, you should extract it's boxed value and pass that by reference directly. Passing a shared_ptr by reference has fairly niche applications and allows the callee to do things like reset the shared_ptr, extract a weak_ptr from it, etc. That said, if you are in need of the latter use case, it certainly should be passed by reference. It's not just a reference count! Shared pointers in C++ are threadsafe so there's a fair bit more going on under the hood that makes copying it (more) expensive.
- Matthias247 9y agoI agree with the last sentence. Nevertheless, if it's mainly a learning project for the author, I don't think there's anything wrong with writing it. Some technical review for the presented library: - It doesn't seem to support any kind of backpressure, which is basically a nogo if you want to build something reliable on top. On the receiving side you will always get data pushed via callbacks without the possibility to stop it. On the sending side it will always return void and queue the data internally if it can't be send immediatly. A slow, malfunctioning or attacking remote can DOS you through that. Ways to implement backpressure are pull-style operations like in boost asio (you start a read and get a single callback when it's done) or some pause/unpause functions and buffer treshold indicators (like in node.js). I personally prefer the first model now, especially if the single operations return something like a promise. - That brings me to the next point: The framework does not seem to have a good way to build composable operations. E.g. build a function that reads a websocket frame from the socket. Or another function that performs the websocket handshake by reading the HTTP handshake request and sending the associated response, but leaving the stream intact for any following user to to be able to use if for sending websocket frames. And ideally all operations should be trivially boundable by timeouts. With having a single receive callback for available data there's mostly a need for complex callback-driven state machines. - Imho a new good framework should also provide a sophisticated and universal story for cancellation of composed operations. Like backpressure that's a thing which can be avoided for demo applications, but for battleproof production environments it is necessary. - Thread safety and data races: There seem to be a few issues, e.g. TcpConnection::state isn't synchronized and used from multiple threads. loop_->runInLoop([&](){ this->shutdownInLoop(); }); will segfault or cause undefined behavior if the TcpConnection object was deleted befor the queued functor runs. There also might be some reentrancy issues: In each callback to the user (like MessageCallback) the user might fiddle around with the object and change it's internal state. If that isn't expected and guarded against then code that runs after the invocation of the callback might not work as intended. By the way: That's the situation where js-style promises shine: As the callbacks are not immediatly invoked but in the next eventloop iteration there is less rooom for errors. But of course it costs additional performance. If these things now sound as a harsh critique let me try to bring it back into relation again. First of all: Network programming is super hard because of "concurrency everywhere". There are always some execution paths that one hadn't thought about before, and it takes a lot of time to learn all the gotchas. I do that stuff now for 8 years, probably had worse assumptions and code for quite some time, and still learn now things every day. It's for sure not a bad idea to write an own library in order to learn these things. For users the well-known libraries (asio, libuv, QT Network, etc.) might be a more solid choice. Also in my opinion even the big and well-known libraries have some dark corners, there hasn't been a golden solution to network programming yet: - asio is hard to use, callback that are happening on invalidated objects or operations that are still running and use invalidated buffers are are common problem for non-experts. It get's worse if you use asio with multiple threads (especially one io_service and multiple threads). Composed operations are possible but hard to write efficiently (best put all shared-state between operations in shared_ptr's and write a state machine. Maybe it's better with coroutine support. - libuv is generally well engineered, but is still doesn't offer lots of support for higher level composed operations and cancellation. - Netty has some dark corners to watch out for. E.g. if handlers are exchanged during runtime (e.g. for websocket upgrades) or handlers are running in multiple threads there's quite some room for errors on the user side. Otherwise it's a well engineered framework in many areas. - node.js stream abstractions with their multiple modes can be tricky to understand and to use for higher-level abstractions. I guess if networking would be based on promises with async/await support it would be easier now - but those weren't available back then. Imho the most promising concepts for network programming are the coroutine based ones. Go's model works well, is on the easier side to use (even though goroutines/threads introduce more possibilities for race conditions). It ticks most boxes, e.g. backpressure is naturally available through sync APIs. Cancellation could probably be improved. Martin Sustriks experiments with libdill also look interesting. As well as Kotlins coroutine model. The promise based models with async/await are also quite promising, e.g. in C# or node.js. However I find those models fall a little bit down as soon as they go to support both multiple threads and an event loop. Having to remember which callbacks/continuations run on which thread and what is allowed there is cumbersome. Imho either multiple threads with synchronous code or a single thread with an eventloop is ok. Ooops, that was now a little bit more text than I intended to write. But maybe it helps someone.
- dis-sys 9y agohad a quick look at the src/tests, from what I can tell, it is more like a hobby project started for learning c++11/networking. a few of those tests are really more like examples
- LeoNatan25 9y agoGood, because the readme is severely lacking in any samples. With a claim of "Simple API”, not providing samples in the readme is a sin.
- thiggy 9y agoIts interesting that I can't find a comment in this thread that speaks to API design or how easy it is to use.
- tyteen4a03 9y agoThe link seems to be gone.
- louiz 9y agoIndeed. I hope it has not been deleted because many comments here are mostly negative…
- leohotfn 9y agoApology for my rudeness, I deleted this repository two days ago.