9. What are the pros and cons of the different IPC methods?
Named (or anonymous) Pipes
Use file APIs, so relatively simple to implement if you're at all file-savvy. Not queued.
Connection-oriented, i.e. point to point, and therefore can't broadcast. Win9x can act as
a named pipe client, but not as a named pipe server. NT can do both.
Queued, connectionless and can therefore broadcast. Simple to use, but have some drawbacks:
- Because the sender doesn't know what protocols are installed
on the receiver, mailslot messages are duplicated on every installed protocol, and it's
responsibility to sort out the resulting mess (usually with some sort of tagging system).
- A length limit of 400 bytes or so.
- Don't have guaranteed delivery, though I've yet to see one
fail to arrive (on a LAN : see point 4).
- Broadcasting to a group (e.g. a domain) works fine... until
you want to do it outwards over a RAS link. Then it just plain breaks. You won't find this
fact documented anywhere, as far as I can find. But it bit me, it bit Intel, and it will
bite you as well. Microsoft explained this blocking behaviour to me as their
desire not to flood another network with broadcast UDP, which is fair
enough... if they'd actually got it right. In actuality, about one message
in 6 gets through.
Very simple to use. Obviously message based, so you have to pump messages. If
you need something quick and dirty for occasional-use messaging, both apps (or
at a minimum the receiver app) have a message pump and you can get a window
handle, this is hard to beat.
Memory Mapped files
MMFs don't necessarily need to be associated with a disk file, so you can use them for
IPC. Since MMFs are the underlying implementation technique for most of the other IPC
methods, you won't get much better performance if a shared memory technique fits your
DLL Shared Sections
These require you to write a DLL of course, which seems like overkill just to get two
processes talking. There is also a technical problem which can arise because Windows
recognises DLLs by their path, not their name. So two copies of the same DLL from
different paths can get loaded, and the loading processes won't see the same section. Bummer.
Another problem arises because of changes to Windows made around the time of Windows 2000.
Because of the rise on importance of virtualisation in general and terminal server in
particular, sharing data across session boundaries was thought to be a security risk.
Hence MS deliberately broke the operation of shared sections across sessions. Each session
gets its own copy of the data, shared only within that session. This means that on Vista
and Windows 7 with their service hardening feature that puts the services into their own
session and the console in a different one, you can't share data between apps and services
using a shared section. Fortunately Memory Mapped Files still work across sessions, so you
can always use one of those. I recently converted a complex shared section DLL to use multiple
MMFs and the job took just over a day, so... pretty easy.
DDE / NetDDE / ddeml
Message based shared-memory technique. Functional, but supposedly moribund. I can only
assume MS doesn't want us to use it because either (a) it doesn't consume enough processor
cycles to keep Intel happy, or (b) it works. Can cause problems because of the broadcast
initiate sent via SendMessage. SendMessage is synchronous and the broadcast goes to every
window in the system, so if someone out there has a window but isn't pumping messages,
your call to SendMessage won't ever return (Win32 uses GetMessage, PeekMessage and
WaitMessage as synchronisation points, so despite the fact that SendMessage is supposed to
be a direct call to your WndProc, it won't get actioned). The cure is to use the
Microsoft's Winsock is based upon the Berkeley Unix sockets implementation, with
proprietary (naturally, this is Microsoft) extensions. Those extensions include support
for asynchronous socket calls. Sockets have the advantage of simplicity and portability
for heterogeneous environments. If you are working with Internet-aware applications,
sockets are your IPC of choice.
There are two types of sockets, stream (TCP) and datagram (UDP). TCP is point
to point and offers guaranteed in-order delivery. UDP supports broadcast, is
size-limited and offers none of the above. Note that stream sockets by their
very nature do not support framing : one of your messages may be split across
two or more packets, so your protocol must take account of this (i.e. one
receive notification != one whole message).
Under Windows, there are various implementation techniques available to you.
||Basically, using worker threads and blocking socket calls. This is
simple to implement, but doesn't scale at all well.
||Asynchronous : Overlapped I/O
||Finicky to code, and doesn't really offer any advantage over the next
||Asynchronous : windows-message notification (a.k.a. the WSAAsyncSelect
||Using the function WSAAsyncSelect, you specify that you want to receive
notifications of socket events via the windows message queue. Upon receipt
of the event, calling a specified function resets the notification ready for
the next event. If you have a GUI app and maximal throughput isn't a
necessity, this is a good bet.
||Asynchronous : I/O Completion Ports
||In this technique events are queued through
an I/O completion port, so it
combines the convenient queueing of the WSAAsyncSelect method with the
performance of overlapped I/O. For non-GUI apps, or those that require
extreme throughput, this is a good bet. Quality sample code is also
available from www.mvps.org !
Note - Winsock 2.0 supports socket communications over
protocols other than TCP/IP.