AsyncNet (beta)
AsyncNet is an asynchronous network library modeled after Twisted Python.
Unlike Twisted, it is multithreaded. Like Twisted, it is easy to use.
Please note that this is an unfinished early release. Many classes in the
download appear to have no purpose at all, because I am developing support for the
Perspective Broker protocol. When Perspective Broker support is finished, everything
will become clear. I have also not posted the unit test code, because it requires
many of these components.
AsyncNet's license is Zlib-style.
Version History
#-1 June 26, 2009:
Early test release.
Implementation Notes
Thread safety:
Multithreading is done using asynchronous calls to System.Net.Socket. On Windows, this means I/O completion ports and the completion port thread pool.
IStreamTransport methods (Send, Disconnect) are guaranteed to be thread safe, and methods such as DataReceived and Disconnected will always arrive serially for each client. If you do not share state between clients, your StreamProtocol do not need synchronization.
More than one connection can be accepted simultaneously, so server-side factories need synchronization if they set up shared state in BuildProtocol(). If your factory does not set up shared state, your factory does not need synchronization.
Overhead:
When the library receives data, it does not make a copy of it when it calls DataReceived. Instead it gives you an ArraySegment into the received buffer, and the buffer is reused after DataReceived returns. If you need to store received data after returning from DataReceived, make a copy of the data. This lack of copying allows AsyncNet to have almost no overhead for receiving.
When you send data by calling IStreamTransport.Send, the ArraySegment you pass is queued in a Deque of struct type. If the size of the queue is sufficient, no reallocation will be necessary. I expect this to be the usual case. AsyncNet does not make a copy of the data you send. If you need to reuse the same bytes within the array, make a copy of the data. This lack of copying allows AsyncNet to have almost no overhead for sending.
This arrangement means that, for a simple byte-based server, AsyncNet performs no explicit per-receive or per-send memory allocation. Its overhead should be tiny.
Higher level stuff:
DelimitedPacketProtocol and LengthPrefixedPacketProtocol buffer their data (largely because I haven't needed them to be faster), but the buffer is circular, so the same rule applies to Delimited's (Line/Raw)DataReceived and LengthPrefixed's PacketReceived - make a copy if you need it after your callback returns.
LineProtocol and IrcProtocol work with .NET strings and AsyncNet.ByteStrings, which make copies.