Endpoint Library Documentation: Winsock Classes

The Winsock classes currently wrap the asynchronous (WSAAsyncSelect() and friends) and synchronous Winsock 1.1 APIs. These are currently the only concrete subclasses of Endpoint, but the library allows many other types of subclasses.

WinsockStreamEndpoint class diagram


WinsockStreamEndpoint is a ConnectableEndpoint for TCP sockets. (One day, I may write a UDP version called WinsockDatagramEndpoint.) Some of the minor things it handles include adding a few extra Connect and Listen functions that make sense under Winsock, and handling basics like starting up and shutting down Winsock.

More importantly, WinsockStreamEndpoint handles the host name and address lookup functions. Although Winsock provides both asynchronous and synchronous lookup functions, I've found that asynchronous name lookups can be a pain, so I've avoided them in AsyncWskEndpoint. That means that the behavior is commmon between synchronous and asynchronous sockets, so I've placed it up here. Perhaps one day the behavior will split and migrate, but the interface should stay the same.

WinsockStreamEndpoint subclasses diagram


AsyncWskEndpoint manages asynchronous Winsock connections. It makes a lot of use of multiple-inheritance because it has to fulfill several roles. First, it obviously needs to be a WinsockStreamEndpoint. It is also "managed" because the class has to manage memory on the fly as data comes in asynchronously. Because of the way the management interface is structured, you also get the ability to select in a custom block manager as well, giving your program the freedom to simply deal with complete data blocks, rather than having to deal with an unstructured stream of data. Finally, AsyncWskEndpoint inherits from CWnd so it can catch the Winsock window messages. (The OWL version inherits from TWindow instead, among other small differences.)

Using AsyncWskEndpoint is reasonably simple. You create the object, create its memory manager and block manager, and select them in. (In the MFC version, you must also call Create.) Then, you call the member functions as described in the header file. As things on the network happen, AsyncWskEndpoint sends you messages; the default message number is NEndpoint::kClientNotificationEventID, but this can be changed with a call to AsyncWskEndpoint::SetNotificationMessage.

In each of these messages, the LPARAM value is a pointer to the Endpoint object sending the message. This lets a single message procedure handle messages from more than one Endpoint and still differentiate between them. The WPARAM value of these messages is listed below with details about when it is sent:

WPARAM Value Sent When...
kDataReady A completed data block arrives on the connection, according to the selected BlockManager.
kDoneWriting A block of data has been sent. This message is semi-obsolete: it used to be used to tell a program when it was okay to release memory, but the new MemoryManagers handle this functionality now.
kLostConnection The connection to the server drops. (This message might be split so that expected disconnections are differentiated between unexpected ones. Opinions are welcome!)
kConnectionAccepted The server has accepted our connection.
kConnectionRequested A client is trying to connect to the port we're listening on.
kAsyncError Winsock has reported some kind of error.


SyncWskEndpoint is even simpler than AsyncWskEndpoint, and its interface shows it. The only thing it adds to the WinsockStreamEndpoint interface is the Wait() function, which is analogous to Winsock's select() function. The MiniPOP server example, included with the package, shows you pretty much everything you need to know to use this class, especially in the context of a multi-threaded server. The only hard part is pulling the Endpoint stuff out from under all that POP3 stuff! Seriously, the program is reasonably well-architected (it went from concept to finished product in a day and a half, so don't expect too much...), so it shouldn't be hard to pull the relevant info out, especially if you're already familiar with Winsock or BSD sockets.

You will notice that SyncWskEndpoint is not managed. The reason for this is that it is meant to be accessed synchronously, in blocking fashion. So, the client has complete control over memory management already, and there is no reasonable place within SyncWskEndpoint where block management can reside. However, you might choose to add a layer of your own, deriving from ManagedEndpoint and defining some custom block managers. The trick then is to figure out how to pump the data into the block manager. Or, you could just use AsyncWskEndpoint, hint, hint.

Last modified on 6 October 2001 at 06:53 UTC-7 Go to my home page