<< |
Winsock Programmer's FAQ |
>> |
CSocket Considered Harmfulby Warren Young If you're an MFC user, you've probably thought about using the library's CAsyncSocket class or one of its derivatives. Unfortunately, the entire hierarchy has problems that you should know about before you start writing code. CAsyncSocketCAsyncSocket is a bare-bones asynchronous sockets wrapper. There are now two examples in the FAQ that show straight-to-the-API and CAsyncSocket-based clients. If you download and study the examples, you can see that the CAsyncSocket version isn't much smaller, and it has a couple of problems. First, CAsyncSocket does synchronous DNS lookups, so a slow DNS server can cause a program to block for a very long time. Second, you can't derive a class from both CAsyncSocket and CWnd, because they have a base class conflict that the compiler can't resolve. This means you can't set up network timeouts, among other things. This is a design mistake: CAsyncSocket should have been derived from CWnd, because it receives window messages from Winsock. (That would let you have Window timers, too.) Instead, CAsyncSocket creates a separate window to handle these messages. CSocketWith CSocket the trend goes from mediocre to bad. CSocket is a subclass of CAsyncSocket that "fakes" blocking I/O using
asynchronous sockets by running a small message pump every time it gets
a CSocket has outright bugs, too: CSocket tends to crash or raise assertions when used in nontrivial situations. Who ever heard of a network app worth using that didn't get pushed beyond its original design specs? The most damning criticism of CSocket, though, is that true blocking sockets are easy to come by: Winsock blocking sockets are dead easy to program. Why would you choose fake and buggy blocking sockets when you can get bug-free blocking sockets that are less complex to boot? CCESocketCAsyncSocket and CSocket don't work on Windows CE because it only supports Berkeley-style blocking and nonblocking sockets. Microsoft didn't want to give up asynchronous notification, so they committed designicide once again: there's now a subclass of CSocket (!) called CCESocket that emulates asynchronous notifications using a pair of worker threads and blocking sockets. ConclusionLet's summarize the story: First we had asynchronous sockets. Then
we added a layer on top to make those asynchronous sockets look
synchronous. Then we added a layer on top of that that uses synchronous
sockets CSocket breaks the "is a" rule of good object oriented design. With this hierarchy, Microsoft is saying, "a blocking socket is an asynchronous socket, and a sorta-asynchronous thread-based socket is a blocking socket, but not necessarily the reverse." I feel like I'm watching The Three Stooges... The only class in the hierarchy that's at all usable is CAsyncSocket, but usable isn't the same thing as useful. If my needs are simple, it's nearly as easy to write straight Winsock API code. If I have tough networking problems to solve, I use an intelligent class library that does more than simply wrapping Winsock. Such wrappers offer features like buffering and dissection of TCP streams into logical packets. (You can find several on the Libraries page.) Given these resources, why would I ever want to use CAsyncSocket? The cause of this design mess is obvious to any student of Microsoft design history: they started with a usable idea, and then repeatedly added layers to it without considering whether the new layer actually fits conceptually within the existing framework. Refactoring is a foreign concept to Microsoft. At best they'll deprecate an old interface, but even that's usually a toothless threat. How many deprecated and never-documented Win16 APIs are in Win2000? Bad design is a sign of messy thinking. That's not a helpful trait for someone writing foundation libraries. |
<< WsControl() Revealed | Book and Software Reviews >> |
Last modified on 26 July 2000 at 12:52 UTC-7 | Please send corrections to tangent@cyberport.com. |
< Go to the main FAQ page |
|
<<< Go to my Home Page |