I racking my brain over here trying to implement an asynchronous implementation for raw sockets.
At a high level:
Server sends data to clients. Each data has unique 64 bit header identifying the transaction with the client.
Clients respond with the same 64 bit header.
Need an async interface on the server to run multiple transactions concurrently.
Have to use a single raw socket on the server.
This kind of feels like I am implementing my own TCP stack in terms of complexity. I currently have a synchronous API (server can perform one transaction at a time with clients), but I am trying to move to async API so I can do more than one transaction at once.
Do I need to hand-roll my own event loop?
I am thinking I could have some type of hash table to may the 64 bit transaction header to callbacks, but it feels like I may be re-inventing stuff that might already exist.
Can I accomplish this with libxev? Would it even be worth it?
When you say “raw sockets”, are you referring to transporting IP (not TCP) packets back and forth? That is really low-level, and I don’t think you will find much support for those already in place – maybe libpcap could be a starting point.
If you mean that you want to use datagram sockets, you will be using the UDP protocol (again, not TCP). In this case the “event loop philosophy” applies: you either use one of the well-known portable event loop implementations out there (libevent, libuv, libxev, maybe others) or you roll out your own by calling the OS primitives (select, poll, epoll, kqueue, completion ports, etc) – and deal with whatever portability requirements you may have.
Yeah, I’m afraid you will have to rollout everything yourself.
If you do find a library that helps with this, could you please share it here?
From the mists of time, I do remember once using ACE, a C++ library to implement what amounted to ping. This was eons ago. The library is still supported, but I guess it would be considered old-style by now.
“Concurrency” and “asynchronicity/synchronicity” are orthogonal things.
You can do things concurrently without (true) asynchronous input/output,
i.e. using readiness notifications / reactor pattern (POSIX poll(), Linux specific epoll, FreeBSD specific kqueue). If you want (truly) asynchronous input/output, i.e completion notifications / proactor pattern, then IOCP on Windows, io_uring on Linux.