A simple hello world TCP-IP program tends to be disturbingly large and complex, and windows TCP-IP is significantly different from posix TCP-IP.
Waiting on network events is deadly, because they can take arbitrarily large time, but multithreading always bites. People who succeed tend to go with single thread asynch, similar to, or part of, the window event handling loop.
Asynch code should take the form of calling a routine that returns immediately, but passing it a lambda callback, which gets executed in the most recently used thread.
Interthread communication bites – you don’t want several threads accessing one object, as synch will slow you down, so if you multithread, better to have a specialist thread for any one object, with lockless queues passing data between threads. One thread for all writes to SQLite, one thread for waiting on select.
Boost Asynch supposedly makes sockets all look alike, but I am frightened of their work guard stuff – looks to me fragile and incomprehensible. Looks to me that no one understands boost asynch work guard, not even the man who wrote it. And they should not be using boost bind, which has been obsolete since lambdas have been available, indicating bitrot.
Because work guard is incomprehensible and subject to change, will just keep the boost io object busy with a polling timer.
And I am having trouble finding boost asynch documented as a sockets library. Maybe I am just looking in the wrong place.
A nice clean tutorial depicting strictly synchronous tcp.
Libpcap and Win10PCap provide very low level, OS independent, access to packets, OS independent because they are below the OS, rather than above it. Example code for visual studio.
Simple sequential procedural socket programming for windows sockets.
If I program from the base upwards, the bottom most level would be a single thread sitting on a select statement. Whenever the select fired, would execute a corresponding functor transfering data between userspace and system space.
One thread, and only one thread, responsible for timer events and transferring network data between userspace and systemspace.
If further work required in userspace that could take significant time (disk operations, database operations, cryptographic operations) that functor under that thread would stuff another functor into a waitless stack, and a bunch of threads would be waiting for that waitless stack to be signaled, and one of those other threads would execute that functor.
The reason we have a single userpace thread handling the select and transfers between userpace and systemspace is that that is a very fast and very common operation, and we don’t want to have unnecessary thread switches, wherein one thread does something, then immediately afterwards another thread does almost the same thing. All quickie tasks should be handled sequentially by one thread that works a state machine of functors.
The way to do asynch is to wrap sockets in classes that reflect the intended use and function of the socket. Call each instance of such a class a connection. Each connection has its own state machine state and its own message dispatcher, event handler, event pump, message pump.
A single thread calls select and poll, and drives all connection instances in all transfers of data between userspace and systemspace. Connections also have access to a thread pool for doing operations (such as file, database and cryptography, that may involve waits.
The hello world program for this system is to create a derived server class that does a trivial transformation on input, and has a path in server name space, and a client class that sends a trivial input, and displays the result.
Microsoft WSAAsync[Socketprocedure] is a family of socket procedures designed to operate with, and be driven by, the Window ui system, wherein sockets are linked to windows, and driven by the windows message loop. Could benefit considerably by being wrapped in connection classes.
I am guessing that wxWidgets has a similar system for driving sockets, wherein a wxSocket is plugged in to the wxWidget message loop. On windows, wxWidget wraps WSASelect, which is the behavior we need.
Microsoft has written the asynch sockets you need, and wxWidgets has wrapped them in an OS independent fashion.
WSAAsyncSelect
WSAEventSelect
select
Using wxSockets commits us to having a single thread managing everything. To
get around the power limit inherent in that, have multiple peers under
multiple names accessing the same database, and have a temporary and
permanent redirect facility – so that if you access peername, your
connection, and possibly your link, get rewritten to p2.peername by peers
trying to balance load.
Microsoft tells us:
receiving, applications use the WSARecv or WSARecvFrom functions to supply buffers into which data is to be received. If one or more buffers are posted prior to the time when data has been received by the network, that data could be placed in the user’s buffers immediately as it arrives. Thus, it can avoid the copy operation that would otherwise occur at the time the recv or recvfrom function is invoked.
Moral is, we should use the sockets that wrap WSA.
reaction.la gpg key 154588427F2709CD9D7146B01C99BB982002C39F
This work is licensed under the Creative Commons Attribution 4.0 International License.