This example shows you how to build another simple server. The basic structure is very similar to the
Basic Echo Server example and you should go and read about that first and have a good understanding of how everything fits together. This document will only cover the differences between the
Basic Echo Server example and this example.
This example is shipped with all licensed versions of The Server Framework and it requires the core server framework libraries (see
here for licensing options). You can always download the latest version of this example from
here; and although you will need the correct libraries to be able to build it you can look at the example code and see how it works and perhaps get ideas from it. A compiled, unicode release, build of this example is available on request if you require it for performance analysis of the framework.
The main difference between this server and the
Basic Echo Server is that this server used
AcceptEx() to accept new socket connections. This means that the only significant code change between the two examples is that this example derives from
JetByteTools::Socket::CStreamSocketServerEx rather than from
JetByteTools::Socket::CStreamSocketServer.
The implications of this change are that the server uses one less thread to do its work.
JetByteTools::Socket::CStreamSocketServer has a thread that runs to manage accepting new connections. Each time there's a new connection established this thread wakes up (when accept() returns) and does some work. It then calls accept() again and goes back to sleep.
This server, derived from
JetByteTools::Socket::CStreamSocketServerEx, doesn't do any of that. It posts some overlapped AcceptEx() requests when the server starts accepting connections but it does this from the thread that calls
StartAcceptingConnections()
. It then posts more overlapped AcceptEx() calls from whichever I/O thread is handling the completion of an AcceptEx() call. So, as existing calls complete and new connections are established new potential connections are queued up. This is considerably more efficient as there's one less thread to be scheduled and one less thread to contend for server resources (such as buffer or socket allocators). It also allows for servers that scale better; in servers that listen on multiple ports there's an extra thread per port if the server is based on
JetByteTools::Socket::CStreamSocketServer rather than
JetByteTools::Socket::CStreamSocketServerEx.
So, why do we support the other way if it's less efficient? AcceptEx() is a microsoft extension function for Winsock as such you may be writing code on a platform where it's not supported. It's unlikely, but possible. Although most of the example servers use
JetByteTools::Socket::CStreamSocketServer this is historical. Consider using
JetByteTools::Socket::CStreamSocketServerEx unless you can come up with a valid reason not to!
Note that at this time
JetByteTools::Socket::CStreamSocketServerEx does not support accepting a new connection and reading data from that connection at the same time. This is planned for a future release but at present we have no customers who actually really need this functionality and protecting against denial of service attacks on that kind of architecture is 'non-trivial' without adding a watch-dog thread to the system.