Computer network programming
Computer network programming involves writing computer programs that enable processes to communicate with each other across a computer network.
Network programming is client-server programming
Interprocess communication, even if it is bidirectional, cannot be implemented in a perfectly symmetric way: to establish a communication channel between two processes, one process must take the initiative, while the other is waiting for it. Therefore, network programming unavoidably assumes a client-server model: The process initiating the communication is a client, and the process waiting for the communication to be initiated is a server. The client and server processes together form a distributed system. In a peer-to-peer communication, the program can act both as a client and a server.
Network programming is socket programming
The endpoint in an interprocess communication is called a socket, or a network socket for disambiguation. Since most communication between computers is based on the Internet Protocol, an almost equivalent term is Internet socket. The data transmission between two sockets is organised by communications protocols, usually implemented in the operating system of the participating computers. Application programs write to and read from these sockets. Therefore, network programming is essentially socket programming.
Standard API
The reference application programming interface for socket programming is the Berkeley (or BSD) sockets API, first introduced in 1983, which has evolved into a POSIX standard. Application programs create, control, and use sockets through system calls like socket()
, bind()
, listen()
, connect()
, send()
, recv()
.
Messaging Application Programming Interface
Messaging Application Programming Interface (MAPI) is a messaging architecture and a Component Object Model based API for Microsoft Windows. MAPI allows client programs to become (e-mail) messaging-enabled, -aware, or -based by calling MAPI subsystem routines that interface with certain messaging servers. While MAPI is designed to be independent of the protocol, it is usually used with MAPI/RPC, the proprietary protocol that Microsoft Outlook uses to communicate with Microsoft Exchange.
Simple MAPI is a subset of 12 functions which enable developers to add basic messaging functionality. Extended MAPI allows complete control over the messaging system on the client computer, creation and management of messages, management of the client mailbox, service providers, and so forth. Simple MAPI ships with Microsoft Windows as part of Outlook Express/Windows Mail while the full Extended MAPI ships with Office Outlook and Exchange.
In addition to the Extended MAPI client interface, programming calls can be made indirectly through the Simple MAPI API client interface, through the Common Messaging Calls (CMC) API client interface, or by the object-based CDO Library interface. These three methods are easier to use and designed for less complex messaging-enabled and -aware applications. (Simple MAPI and CMC were removed from Exchange 2003.)
MAPI was originally designed by Microsoft. The company founded its MS Mail team in 1987, but it was not until it acquired Consumers Software in 1991 to obtain Network Courier that it had a messaging product. Reworked, it was sold as MS PC Mail (or Microsoft Mail for PC Networking). The basic API to MS PC Mail was known as MAPI version 0 (or MAPI0). MAPI uses functions loosely based on the X.400 XAPIA standard.
Handling Message Items
The Message object provides methods for copying, moving, and deleting messages. An automated email client may need to move incoming helpdesk inquiries, for example, to an appropriate folder for later retrieval by the next available technician.
To move an email message from one folder to another, use the Message object's MoveTo method. Its syntax is: Set CdoMessage2 = CdoMessage.MoveTo(FolderID[, StoreID])
The parameters are:
FolderID
A string that identifies the folder to which the message is to be moved. A folder ID string is obtained from the ID property of a CDO Folder object. Obtaining CDO Folder objects representing specific folders is the subject of the next section.
StoreID
This optional parameter is a string that identifies the message store containing the target folder. If omitted, CDO assumes that the target folder resides in the same message store as the folder from which the message is being moved. A message store ID is obtained from the ID property of a CDO InfoStore object.
Hidden Messages
MAPI folders are considered to have two areas for storing message objects: the standard part and the associated part. The standard part includes messages and folders that are manipulated by the average user. These are the messages and folders that we have been working with so far in this book. The associated part is for storing additional information that is not directly manipulated by the user, such as form definitions, views, rules, reply templates, and more. It is up to the individual messaging client to decide what it will store in hidden messages, and how it will be formatted.
In CDO, associated messages are accessed through a Folder object's HiddenMessages property. The HiddenMessages property returns a Messages collection object that in turn contains Message objects representing associated messages. Example 7-2 shows two utility subroutines that together show any associated messages currently in the user's default message store. The code writes its output to a text file, and then launches the Notepad program to display the output. A sample of the output is shown in Figure 7-2. The figure shows that in this user's Calendar folder (which was created by Microsoft Outlook) there are two hidden messages. The first hidden message has a subject of "LocalFreebusy". Further, this message has a message class of "IPM.Microsoft.ScheduleData.FreeBusy". This is intriguing, isn't it? It's tempting to reverse engineer this further in an attempt to write code that modifies the behavior of Outlook. However, because this information is undocumented, it is subject to change without notice, thereby threatening that your application won't work with future versions of Outlook. It's better to use this information to expand your understanding of messaging, without relying on it remaining unchanged for the correct functioning of your applications.
_____________________________________________________________________________________________________________________________________________________________
_____________________________________________________________________________________________________________________________________________________________
DLL
You make an ActiveX DLL or EXE to allow multiple applications to share the same code. This saves you time because you only need to write the code once. It also lets you devote extra time to debugging the shared code. If you are going to use the code in a lot of different applications, you can perform extra tests to make sure the code works correctly and still save time overall.
Centralizing the code also lets you fix, upgrade, and otherwise modify the shared library relatively easily. You can update the shared DLL/EXE and all of the applications that use it are automatically updated. The Binding section talks more about this.
ActiveX DLLs and ActiveX EXEs are almost exactly the same in the ways they are built and used. In both cases, you build one or more classes that applications can use to do something. The big difference lies in where they are used.
An ActiveX DLL's code is executed within the main program's address space. It behaves as if the class was created within the main program's code. Because the code lies inside the program's address space, calling methods is very fast. An ActiveX EXE's code is run in a separate process. When the main program calls an ActiveX EXE's method, the system marshalls the call to translate the parameters into the ActiveX EXE's address space, calls the method, translates the results back into the main program's address space, and returns the result. This is slower than running an ActiveX DLL's method inside the main program's address space.
Because of the difference in speed, an ActiveX DLL is almost always preferable. The reason ActiveX EXEs are useful is they can run on a different computer than the main program while an ActiveX DLL must run on the same computer as the main program. If you want to build a library of shared routines to save programming and debugging, use an ActiveX DLL because it will give you better performance. Even if you need to distribute several copies of the DLL on different computers, it will probably be worthwhile.
If you want a centralized server library, use an ActiveX EXE. The EXE can sit on a central computer and work directly with that computer's resources. If you need to frequently change how the code works, you can easily change it in one place.
_____________________________________________________________________________________________________________________________________________________________ _____________________________________________________________________________________________________________________________________________________________
URl Moniker
The OLE moniker architecture provides a convenient programming model for working with URLs. The moniker architecture supports extensible and complete name parsing through the MkParseDisplayName function and the IParseDisplayName and IMoniker interfaces, as well as printable names through the IMoniker::GetDisplayName method. The IMoniker interface is the way you actually use URLs you encounter, and building components that fit into the moniker architecture is the way to actually extend URL namespaces in practice.
A system-provided moniker class, the URL moniker, provides a framework for building and using certain URLs. Because URLs frequently see resources across high-latency networks, the URL moniker supports asynchronous as well as synchronous binding. The URL moniker does not currently support asynchronous storage.
Like all moniker clients, a user of URL Monikers typically creates and holds a reference to the moniker as well as to the bind context to be used during binding (IMoniker::BindToStorage or IMoniker::BindToObject). To support asynchronous binding, the client can implement a bind-status-callback object, which implements the IBindStatusCallback interface, and register it with the bind context using the RegisterBindStatusCallback function. This object will receive the transport's IBinding interface during calls to IBindStatusCallback::OnStartBinding.
The URL Moniker identifies the protocol being used by parsing the URL prefix and then retrieves the IBinding interface from the transport layer. The client uses IBinding to support pausing, cancellation, and prioritization of the binding operation. The callback object also receives progress notification through IBindStatusCallback::OnProgress, data availability notification through IBindStatusCallback::OnDataAvailable, and various, other transport-layer notifications about the status of the binding. The URL moniker or specific transport layers may also request extended information from the client through IBindStatusCallback::QueryInterface, allowing the client to provide protocol-specific information that will affect the bind operation.
For more information, see the following topics: Callback Synchronization Media-Type Negotiation URL Moniker Functions
Callback Synchronization
The asynchronous WinInet API (used for the most common protocols) leaves the synchronization of the callback mechanism and the calling application as an exercise for the client. This is intentional because it allows the greatest degree of flexibility. The default protocols and the URL moniker implementation perform this synchronization and guarantee that single-threaded and apartment-threaded applications never have to deal with free-thread-style contention. That is, the client's IEnumFORMATETC and IBindStatusCallback interfaces are called only on their proper threads. This feature is transparent to the user of the URL mMoniker as long each thread that calls IMoniker::BindToStorage and IMoniker::BindToObject has a message queue.
The asynchronous moniker specification requires more precise control over the prioritization and management of downloads than is allowed for by either WinSock or WinInet. Accordingly, a URL moniker manages all the downloads for any given caller's thread, using (as part of its synchronization) a priority scheme based on the IBinding specification.
Media-Type Negotiation
Many application-layer Internet protocols are based on the exchange of messages in a simple, flexible format called Multipurpose Internet Mail Extensions (MIME). Although MIME originated as a standard for exchanging electronic mail messages, it is used today by a wide variety of applications to specify mutually understood data formats as MIME, or media, types. The process is called media-type negotiation.
Media types are simple strings that denote a type and subtype (such as "text/plain" or "text/HTML"). They are used to label data or qualify a request. A Web browser, for example, as part of an HTTP request-for-data or request-for-info, specifies that it is requesting "image/gif" or "image/jpeg" Media Types, to which a web server responds by returning the appropriate media type and, if the call was a request-for-data, the data itself in the requested format.
Media-type negotiation is often similar to how existing desktop applications negotiate with the system clipboard to determine which data format to paste when a user chooses Edit/Paste or queries for formats when receiving an IDataObject pointer during a drag-and-drop operation. The subtle difference in HTTP media-type negotiation is that the client does not know ahead of time which formats the server has available. Therefore, the client specifies up-front the media types it supports, in order of greatest fidelity, and the server responds with the best available format.
URL monikers support media-type negotiation as a way for Internet clients and servers to agree upon formats to be used when downloading data in BindToStorage operations. To support media-type negotiation, a client implements the IEnumFORMATETC interface and calls the RegisterFormatEnumerator function to register it with the bind context. The format enumerator lists the formats the client can accept. A URL moniker translates these formats into media types when binding to HTTP URLs.
The possible media types requested by the client are represented to URL monikers through FORMATETC structures available from the IEnumFORMATETC enumerator registered by the caller on the bind context: Each FORMATETC specifies a clipboard format identifying the media type. For example, the following code fragment specifies that the media type is PostScript.
URL Moniker Functions
URL moniker functions insulate developers from the complexities of creating, managing, and using URL monikers. These functions are as follows:
- CreateURLMoniker
- IsValidURL
- RegisterMediaTypes
- CreateFormatEnumerator
- RegisterFormatEnumerator
- RevokeFormatEnumerator
- RegisterMediaTypeClass
- FindMediaTypeClass
- GetClassFileOrMime
- UrlMkSetSessionOption
_____________________________________________________________________________________________________________________________________________________________ _____________________________________________________________________________________________________________________________________________________________
Further Reading
- W. Richard Stevens: UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI, Prentice Hall, 1998, ISBN 0-13-490012-X.