This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


May 1998

Microsoft Systems Journal Homepage

Windows CE 2.0 Networking Offers Exciting Mobile Computing Possibilities

Anthony Jones

Microsoft’s new Windows® CE operating system is designed for small form factor devices. An appealing feature of these devices is their robust networking capability. They support many types of communications hardware, including serial links, modems, and Ethernet cards.

This article assumes you’re familiar with C++ and Network Programming

Anthony Jones is an engineer at Microsoft in the Developer Support Networking Unit. He is an avid skier who is perfecting the technique of sliding down the mountain on his back.

Imagine you're on your way to the airport for an important business trip when you realize you left the heat on at your house. You pull your Handheld PC out of your briefcase and dial up your ISP through your cellular phone. You then bring up a Home Management app that shows the temperature in your house, the thermostat setting, what lights are on, and the mode of the security system, among other things. You turn the thermostat to the off position and the problem is solved. Sound like science fiction? Well, it's closer than you think!
      Microsoft's new Windows® CE operating system is designed for small form factor devices, including Handheld PCs, automobile computers, and many other embedded applications. Just recently, Microsoft and TCI announced a deal to use Windows CE in set top cable boxes. Microsoft has also unveiled plans for the Auto PC, a small computer running Windows CE for use in automobiles. Several manufacturers have already released plans to produce these devices with navigation features that include a GPS (Global Positioning System) tracking device and wireless communications.
      Of course, most people have heard of those tiny Handheld PCs running the Windows CE operating system. These little devices are amazing in their own right. Handheld PCs come with versions of Microsoft Excel and Word, and their ability to synchronize with your desktop PC via serial or infrared connections makes them the perfect personal organizers. Another appealing feature of these devices is their robust networking capability. They support many types of communications hardware, including serial links, modems, and Ethernet cards. They also support almost all of Microsoft's networking APIs!
      Windows CE is taking off like wildfire, in large part due to its strong networking features. In this article I will give a detailed overview of the networking capabilities under Windows CE 2.0. I will emphasize the Winsock support and networking features such as infrared socket support (IrSock) because these capabilities open up exciting new possibilities in the world of mobile computing.
      One important thing to note is that the communications support in Windows CE is an operating system specification and not a requirement for the hardware on which it runs. Handheld PC manufacturers receive the operating system as a set of components, some of which are tagged as optional. The manufacturer can choose which optional features will be supported. When manufacturers leave out a component, it's usually to save space for their own unique features. In the discussion that follows, I will note those APIs that I know are not implemented on Handheld PCs.

Communication Support
      There are three basic components to Windows CE communications: serial I/O, telephony, and networking support. Windows CE networking support includes:

  • Winsock and IrSock APIs
  • TCP/IP and IrDA protocols
  • NDIS4.0 support for local area networking
  • PPP and SLIP via serial or modem connections
  • Remote file access (WNet API)
  • Remote Access Client (RAS API)
  • Browser support (WinInet API)

Serial Communication
      Serial communication is a fundamental feature of the Windows CE architecture and should be available on virtually all devices. Serial communication is performed either over a direct cable connection or through the infrared transceiver. Direct cable connections over a COM port are handled by the Win32® API serial functions. The API calls CreateFile, ReadFile, and WriteFile can be used to open, read from, and write to a COM port. Overlapped (asynchronous) I/O is not supported under Windows CE and should not be used in any of the API calls.
      The infrared port is assigned to a COM port so it is possible to use the Win32 API serial functions to communicate. Since this is raw I/O, there will be no collision detection, which can lead to data corruption. The IrSock extension to Winsock provides reliable communication over the infrared port. In addition, there is IrComm, which emulates a serial connection but uses IrSock and the IrDA protocol under the hood.

Telephony
      Windows CE also includes a telephony (TAPI) service provider that supports AT command-based modems. This capability can be used either with attached modems or PCMCIA modems. The purpose of TAPI is to provide telephone communication services without requiring detailed knowledge of the modem hardware. Currently, Windows CE supports only outbound calls; inbound calls are not supported. Windows CE provides a connection wizard to set up multiple dial-up and direct cable connections.

Networking Communications
      The networking options available under Windows CE are impressive for such a small device. Looking at Figure 1, you can see that at the highest level of the network stack lies the WinInet and WNet APIs. The WinInet API is for Internet browsing support while the WNet API is used to access share drives on remote computers. The WNet API will allow network printing in Windows CE 2.1. Both WinInet and WNet are implemented as a subset of their Win32 counterparts and contain some limitations.

Figure 1  API and Protocol Stack
Figure 1  API and Protocol Stack


      There are some differences in the Windows CE implementation of WinInet. First, most WinInet APIs are handled synchronously. Only InternetReadFile and InternetQueryDataAvailable support both synchronous and asynchronous modes. Second, Windows CE supports Unicode by default. Last, before using any Internet functions, an application must call InternetOpen to obtain a handle that points to an Internet or Gateway object. This handle will be passed to other functions that offer specific Internet services such as issuing an HTTP request.
      Under Windows CE, WinInet is limited to client applications using HTTP and FTP. Gopher, cookies, and persistent URL cache functions are not presently supported. While the FTP APIs are available as a Windows CE component, no Handheld PC currently shipping supports them.
      The WNet API under Windows CE also contains some caveats. Only the Microsoft network provider is supported, which means, for example, you cannot connect to Novell share drives. Also, the redirector was left out of Windows CE 2.0 for the Handheld PC, and this cripples its ability to use any of the WNet functions successfully. However, Microsoft has now made the missing files available for download from their Web site.
      Next are the Remote Access Client and Winsock (along with IrSock). Because Winsock and IrSock are the focus of this article, I will discuss those in greater detail later. The Remote Access Service (RAS) is a software-based multi-protocol router used to connect Windows CE devices to a remote host. Windows CE only provides support for RAS clients. Most of the Win32 RAS functions are present, except those that deal with the server side of RAS. The only other restriction is that RAS supports only one point-to-point connection at any given time, but the connection can be either a direct serial connection or a dial-up connection.
      It is important to note that some networking APIs are not supported under Windows CE. None of the LAN Man API calls are supported, and named pipes and mailslots are not implemented. For further information on WinInet, WNet, and RAS capabilities and limitations under Windows CE, consult the Platform SDK documentation.

Winsock Support
      Windows socket support under Windows CE is a subset of the Winsock 1.1 specification. All of the standard Winsock functions are available except for the asynchronous calls (including the majority of the WSAxxx functions). Some added features include support for Secure Socket Layer (SSL) 2.0, SSL 3.0, and PCT 1.0 security protocols. There is also a set of ICMP support functions used for making "ping" requests.
      Winsock support has been extended to handle the IrDA protocol. This extension is known as IrSock, and brings exciting new capabilities to mobile devices. Applications using IrSock are very similar to straight Winsock applications except that the addressing scheme is new. The new addressing scheme was necessary because of the nature of mobile computing. Handheld PCs frequently move in and out of range of various resources, so a dynamic name resolution scheme was required. I will discuss IrSock addressing in further detail later on.

Handheld PCs on the Network
      Handheld PCs running Windows CE are designed to communicate with other machines. This is perhaps its greatest strength. As discussed earlier, there are several ways to get a Handheld PC connected to other PCs. The first (and most common) method is to connect to a desktop via the serial cable or the infrared serial port. If you have the Windows CE Services installed, a relationship is created between the Handheld PC and PC. These services, however, are not required to use a serial connection. All that is needed is a desktop with the RAS server installed.
      When connecting a Handheld PC to a desktop there are certain limitations. First of all, a connected Handheld PC is not registered with a WINS server unless the redirector components are used. This means that any attempt to resolve the name of the Handheld PC will fail. Second, the Handheld PC is assigned an IP address, but in most cases this address is a local address that is known only to the desktop. This makes it impossible for outside machines to connect to the Handheld PC, but the RAS server will forward the network packets from the Handheld PC to the correct location. Of course, this scenario assumes the typical RAS server setup. It is possible to configure RAS to hand out real IP addresses and configure routing so that the Handheld PC can receive network traffic, but that is beyond the scope of this article.
      A Handheld PC is capable of using an Ethernet card, in which case it could be assigned a real IP address (statically or via DHCP). This would allow a Handheld PC full access to reach and be reached by other machines.

Writing Winsock Applications
      Because the asynchronous Winsock functions are not available, developers must restructure their applications to use regular blocking and nonblocking sockets. Programmers who grew up with Windows sockets might have some trouble thinking of sockets without the window messages and event notifications enabled by WSAAsynchSelect and WSAEventSelect, respectively. I came from a BSD socket background, but I have to admit that the asynchronous Winsock model is rather elegant. It greatly simplifies socket programming when receiving data asynchronously. In this section, I will describe what you need to watch out for when coding blocking and nonblocking sockets, and I will present strategies for efficiently using these models.
      Socket programming must be proactive; that is, the programmer must take into account the many possible actions that could take place at each Winsock call. With asynchronous sockets, reading and writing only take place when their respective events are triggered. This leaves the programmer free to think about how to perform some computation on the data. With synchronous sockets, the programmer must think, "Okay, at this point I need to read 42 bytes, but what happens if the data hasn't arrived yet?" As a result, the programmer needs to develop a well thought out read/write scheme with awareness of the data flow between the application and the remote machine.

Blocking Sockets
      Blocking sockets cause concern because any Winsock API call on a blocking socket may do just that—block for some period of time. Most Winsock applications follow a producer-consumer model where the application reads (or writes) a specified number of bytes and performs some computation on that data. The code snippet in Figure 2 illustrates this model.
      The problem with this code is that recv may never return if there is no data pending because the statement says to return only after reading bytes from the system's input buffer. Some programmers might be tempted to peek for the necessary number of bytes in the system's buffer by calling ioctlsocket with the FIONREAD option. Peeking for data without actually reading the data (reading the data actually removes it from the system's buffer) is considered bad programming practice and should be avoided at all costs. The overhead associated with peeking is great because there are possibly several system calls just to check the number of bytes available. Then, of course, there is the overhead of making the actual read call that removes the data from the system buffer.
      What can be done to avoid this? The idea is to prevent the application from totally freezing due to lack of data (either from network problems or client problems) without continually peeking at the system network buffers. One method is to separate the application into a reading thread and a computation thread that share a common data buffer. Access to this buffer would be protected through the use of a synchronization object such as an event or mutex. The purpose of the read thread is to continually read data from the network and place it in the shared buffer. Once the reading thread has read the minimum amount of data necessary for the computation thread to do its work, it could signal an event which would notify the computation thread to begin. The computation thread would then remove a chunk of data from the buffer and perform whatever calculations are necessary. Figure 3 illustrates this by providing two functions, one responsible for reading network data (ReadThread), and one for performing the computations on the data (ProcessThread).
      One drawback to blocking sockets is that it makes life more difficult if the app needs to communicate via more than one connected socket at a time. The scheme shown in Figure 3 could be modified to have one read and data processing thread per connected socket. This adds quite a bit of housekeeping overhead, but it is a feasible solution. The only drawback is that the solution does not scale very well once you start dealing with a large number of sockets.

Nonblocking Sockets
      The alternative to blocking sockets is nonblocking sockets. Nonblocking sockets are a bit more of a challenge to use, but they are every bit as powerful as blocking sockets and offer a few advantages. Figure 4 illustrates how to create a socket and put it into nonblocking mode.
      Once a socket is placed into nonblocking mode, Winsock API calls will return immediately. In most cases these calls will fail with the error WSAEWOULDBLOCK, which means that the requested operation did not have time to complete during the call. For example, a call to recv for 20 bytes will return WSAEWOULDBLOCK if there is no data pending in the system's input buffer. Often additional calls to the same API are required until a successful return code is encountered. Figure 5 describes the meaning for various Winsock calls when WSAEWOULDBLOCK is returned.
      Because nonblocking calls frequently fail with the WSAEWOULDBLOCK error, it is important to check all return codes and be prepared for failure at any time. Many programmers fall into the pitfalls of continually calling one API call until it returns a success. For example, placing a call to recv in a tight loop to read 200 bytes of data is no better that polling a blocking socket with the MSG_PEEK flag. To avoid this, the select API can be used to detect whether there is data to be read or whether a socket can be written to. This API call will block until the conditions the programmer specifies are met. The function prototype for select is as follows:


 int WINSOCKAPI select(int nfds, 
                       fd_set *readfds, 
                       fd_set *write_fds,
                       fd_set *except_fds, 
                       const struct timeval
                       *timeout);
You'll notice that there are three fd_set parameters, one for checking readability, one for writeability, and one for out-of-band data, respectively. An fd_set is a collection of sockets. Winsock declares several macros for adding, deleting, and clearing these sets. For example, Figure 6 illustrates how to check whether socket s has any incoming data pending.
      A single call to select may also include the other fd_set variables, and each fd_set may contain multiple sockets. To keep things simple, it is probably best to call select with only one type of fd_set at a time because select merely returns the number of sockets that meet the given conditions. For example, if a read and a write fd_set were used with each set containing three sockets, and select returned four, all this means is that four sockets are available for reading or writing. It is up to the programmer to figure out which sockets correspond to which event.
      Each type of socket, blocking and nonblocking, has advantages and disadvantages. Blocking sockets are easier from a conceptual standpoint, but become difficult to use when dealing with multiple connected sockets or when data is sent and received in varying amounts and times. Nonblocking sockets require more code to handle the possibility of receiving a WSAEWOULDBLOCK error on every Winsock call, but the select function offers the ability to manage multiple connected sockets in an organized manner.

Socket Options
      Because Windows CE Winsock is an entirely new and small platform, not all of the socket options used by getsockopt and setsockopt are useful, or even implemented. I'll detail the options that are supported for each API call. Figure 7 enumerates the socket options that are currently supported or will be supported in the future. The first column, Level, shows for which level the option is valid. The Option Name column lists the actual option. The Specific API column notes whether the option applies to getsockopt, setsockopt, or both. Finally, the Protocol column notes whether the option is valid for traditional Winsock sockets, IrSock sockets, or both.
      All of the options in Figure 7 are defined in the Winsock header file, but not all are implemented. For setsockopt there are quite a few options not implemented. First, none of the multicast options (IP_MULTICAST_TTL, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_ADD_MEMBERSHIP, and IP_DROP_MEMBERSHIP) are implemented because multicasts are not supported under Windows CE 2.0. Multicast support is slated for Windows CE 2.1. Note that multicast support for IrSock does not make sense since it does not support datagram sockets. Also, SO_RCVBUF can be used to obtain the system receive buffer size in getsockopt, but it cannot be used to change the buffer. If you do try to change the receive buffer size, the error WSAEOPNOTSUPP will be returned. Options related to the SOL_IRLMP family will be discussed in further detail in later sections.
      The only WSAxxx function implemented under Windows CE is WSAIoctl. Both WSAIoctl and ioctlsocket are used to set or check various input and output options on a socket (see Figure 8). These differ from the getsockopt and setsockopt functions in that they do not apply to any particular socket family or protocol. They handle general options such as blocking versus nonblocking mode and secure socket layer options, and should apply to both Winsock and IrSock, although secure socket options are not supported for IrSock.
      Windows CE includes three new Winsock API functions that perform ICMP echo requests that are similar to the ping command. These new API functions—ICMPCreateFile, ICMPSendEcho, and ICMPCloseHandle—are simple and well documented in the SDK. ICMPCreateFile is called first to return a valid ICMP handle that you use in calls to ICMPSendEcho. This API function lets you send data in an ICMP packet, and returns any ICMP responses from the intended recipient (or returns an error if the network is unreachable). You may also specify a timeout value to limit the waiting time in case the destination is unreachable. ICMPCloseHandle is called on the ICMP handle when communication is finished. Unfortunately, the required header file (icmpapi.h) and static library (icmplib.lib) were left out of the latest SDK, and this will be remedied in newer releases of the SDK or possibly through a Knowledge Base article.

Infrared Sockets
      Most Handheld PCs come equipped with an infrared serial port for wireless communication. IrSock takes into account the transient nature of portable computers. Because Handheld PCs are likely to move about, traditional name resolution schemes (including conventional Winsock) do not work well. These conventional methods assume static resources such as name servers, which cannot be used when a person is walking about with a Handheld PC that is running a network client.
      To circumvent this problem, IrSock is designed to browse in-range resources in an ad-hoc manner without the overhead of a large network, and does not use standard Winsock name service functions or even IP addressing. Instead, the name service has been incorporated into the communications stream, and a new address family has been introduced to support services bound to infrared serial ports.
      The IrSock address structure includes a service name that describes the application used in bind and connect calls, and a device identifier describing the device on which the service runs. This pair is analogous to the IP address—the port number tuple used by conventional TCP/IP sockets. The IrSock structure is defined as:


 struct sockaddr_irda {
     u_short     irdaAddressFamily;
     u_char      irdaDeviceID[4];
     char        irdaServiceName[25];
 };
The irdaAddressFamily field is always set to AF_IRDA. The irdaDeviceID field is a four-character string that identifies the device on which a particular service is running. This field is ignored when creating an IrSock server, but it is significant for a client because it specifies the specific IrDA device to connect to. Finally, the irdaServiceName field is the name of the service that the application will either register itself as or is looking for.

IrSock Name Resolution
      Addressing can be based on IrDA Logical Service Access Point Selectors (LSAP-SELs) or on services registered with the Information Access Service (IAS). The IAS abstracts a service from an LSAP-SEL into a more friendly service name. You can think of this as the difference between an Internet name such as www.microsoft.com and its numeric IP address.
      Developers are discouraged from using the direct LSAP-SEL "address" because the address space for IrDA services is limited. Windows CE allows LSAP-SEL integer identifiers in the range of 1-127. IAS can be thought of as a WINS server. It associates an LSAP-SEL with a service name.
      An actual IAS entry has three fields of importance: class name, attribute, and attribute value. For example, a server wishes to register itself under the service name of MyServer. This is accomplished when the server issues the bind call with the appropriate SOCKADDR_IRDA structure. Once this occurs, an IAS entry is added with a class name of MyServer, an attribute of IrDA:TinyTP:LsapSel, and an attribute value of, say, 3. The attribute value is the next unused LSAP-SEL.
      The client, on the other hand, passes in a SOCKADDR_ IRDA to connect. This initiates an IAS lookup for a service with the class name MyServer and attribute IrDA:TinyTP:LsapSel. The IAS query will return the value 3. It is possible to formulate your own IAS query by using getsockopt with the IRLMP_IAS_QUERY option. I will discuss this later.
      If you want to bypass IAS altogether (although this is not recommended), you can specify an LSAP-SEL address directly for a server name or an endpoint to which a client wishes to connect. This should only be used to communicate with legacy IrDA devices that do not provide any kind of IAS registration. Specifying the service name in the SOCKADDR_IRDA structure as LSAP-SELxxx, where xxx is the attribute value between 1 and 127, bypasses the IAS registration and lookup. For a server, this would directly assign that server to the given LSAP-SEL address (assuming that LSAP-SEL is unused). For a client, this bypasses the IAS lookup and causes an immediate attempt to connect to whatever service is running on that LSAP-SEL.

IrSock Server
      The coding principle behind a server running over IrSock is analogous to the regular Winsock equivalent. To write an IrSock server, first allocate a socket with the socket API call, using AF_IRDA for the address format parameter and SOCK_STREAM for the type. Next, bind the service name to the socket with the bind call, passing a SOCKADDR_IRDA structure in for the address parameter. Listen for incoming connections with the listen API call and accept incoming connections with the accept API call. Use the send and recv API calls to communicate with the client. Finally, close the socket with the closesocket API call.
      Writing an IrSock client is slightly more complicated because it is the job of the client to search for services in the area. This search is a general search for IrDA devices in the vicinity; it actually does not search for a particular service. I will discuss this in more detail shortly.
      But first, here are the general steps necessary to write a client using IrSock. Start by allocating a socket with the socket API call, using AF_IRDA for the address format parameter and SOCK_ STREAM for the type. Then search for available IrSock servers with getsockopt and the IRLMP_ENUMDEVICES option. Connect with the service via the connect API, using a SOCKADDR_IRDA for the name parameter that describes the particular service for which you are looking. Use the send and recv API calls to communicate with the server. Finally, close the socket with the closesocket API call.
      The method for looking up IrSock services is straightforward, but the significant differences from traditional Winsock can cause a few problems. As I mentioned, the basis for looking up available services is getsockopt with IRLMP_ENUMDEVICES. This call will discover devices within the infrared range for registered applications. If any services are found, they are returned in a DEVICELIST structure, which is defined as follows:


 typedef struct _IRDA_DEVICE_INFO
 {
     u_char    irdaDeviceID[4];
     char      irdaDeviceName[22];
     u_cahr    Reserved[2];
 } IRDA_DEVICE_INFO, *PIRDA_DEVICE_INFO, FAR *LPIRDA_DEVICE_INFO;
 
 typedef struct _DEVICELIST
 {
     ULONG            numDevice;
     IRDA_DEVICE_INFO    Device[1];
 } DEVICELIST, *PDEVICELIST, FAR *LPDEVICELIST;
      The field of interest in a DEVICELIST is Device, which is an IRDA_DEVICE_INFO structure. Within that structure is an irdaDeviceID that corresponds to the field of the same name in the SOCKADDR_IRDA structure. Any IrSock-capable device will have a device ID associated with it, so a successful query will return one or more IRDA_DEVICE_ INFO structures containing the device ID of each device discovered. If no IrSock-capable devices are detected, the query will return with the numDevice field set to zero. Once a list of these device IDs are returned, a client can either attempt to connect to each server or begin to query the server for services it is running. To connect to the server, the client fills out a SOCKADDR_IRDA with the device ID of the device in question and the service name of the IrSock server to which it wants to connect.
      You may have noticed that when searching for available IrSock devices, a device ID and friendly name are returned. A client is required to know both the device ID of the server and the name of the IrSock service for which it is looking. Future releases may add additional "hint" information to the structure returned by an IRLMP_ENUMDEVICES call. This information will better associate a particular server with a found IrDA device. To find the correct server, it is necessary to attempt a connection to each device returned, specifying the service name for which you are looking. Figure 9 illustrates a simple IrSock client, irclient.c, that first searches for IrSock devices in the area, and then attempts to connect to each one in search of a particular server. Also included is code for a simple IrSock server to which this client could connect.

IrSock Socket Options
      IrSock exposes a handful of socket options, only a few of which are likely to get much use. The most commonly used option is IRLMP_ENUMDEVICES, which I discus-sed earlier. This is used to browse infrared traffic for available devices. The other commonly used option is IRLMP_IAS_QUERY, which is used to query a device's IAS service for registered services and service attributes. When performing a query, an IAS_QUERY structure is passed into getsockopt, defining the parameters for the search. The structure is defined as follows:


 typedef struct _IAS_QUERY
 {
     u_char  irdaDeviceID[4];
     char    irdaClassName[61];
     char    irdaAttribName[61];
     u_short irdaAttribType;
     union
     {
         int irdaAttribInt;
         struct
         {
             int     Len;
             u_char  OctetSeq[1];
             u_char  Reserved[3];
         } irdaAttribOctetSeq;
         struct
         {
             int     Len;
             u_char  CharSet;
             u_char  UsrStr[1];
             u_char  Reserved[2];
         } irdaAttribUsrStr;
     } irdaAttribute;
 } IAS_QUERY, *PIAS_QUERY, FAR *LPIAS_QUERY;
      An entry within the IAS_QUERY consists of the device ID, class name, and attribute name. The attribute value associated with the name can be an integer, a binary sequence, or a string, which is the reason for the union within the structure. To perform a query, fill in a valid device ID (returned from an IRLMP_ENUMDEVICES), class name, and attribute name. The value returned will be the attribute associated with that particular class and attribute on the given device. For the most part, developers will use connect, which will properly handle the query for the LSAP-SEL on which a service is running. In this case, the device ID would be the device to query, the class name would be the name associated with the service in question, and the attribute would be IrDA:TinyTP:LsapSel.
      Another option of some interest is IRLMP_IAS_SET, which is used to change the attribute associated with a particular class name. This option requires passing an IAS_SET structure into setsockopt. The structure is exactly like the IAS_QUERY structure minus the irdaDeviceID field. It is doubtful that one would actually need to change the attributes associated with an IAS entry.
      The rest of the IrSock options are unlikely to be used, but here are short descriptions of each to satisfy everyone's curiosity. IRLMP_9WIRE_MODE is designed to talk to the Windows 95 IrComm. In this mode, the IrLMP packet contains an additional one-byte IrComm header. Related to this option is IRLMP_SEND_PDU_LEN, which transmits the maximum PDU size of an IrLMP packet to the other side. This is used to determine whether IRLMP_9WIRE_ MODE should be set. IRLMP_EXCLUSIVE_MODE puts the IrLMP layer into exclusive mode, which means only one LSAP-SEL will be active and communicating. For further information about these options, consult the IrDA specifications found at http://www.irda.org.

Secure Socket Layer Support
      Windows CE provides support for SSL, including the SSL 2.0, SSL 3.0, and PCT 1.0 security protocols. Secure sockets are available from both the WinInet API and the Winsock API. To utilize SSL from Winsock, the following steps need to be taken.
      First, create a callback function that will be called by the Winsock security provider when a certificate is received from a remote party. This function is responsible for ensuring the validity of the certificate received. Next, create a socket with the socket API. Set the socket options via the setsockopt API, with the level parameter set to SO_SOCKET, the optname set to SO_SECURE, and the optval (a DWORD), set to SO_SEC_SSL. Call the WSAIoctl API to complete the setup. This includes calling WSAIoctl with the SO_SSL_ SET_VALIDATE_CERT_HOOK option to install the callback function created in the first step. Finally, make a connection and use Winsock calls in the normal fashion.
      The most involved step in the process is writing the callback function for validating certificates. The purpose of the callback is twofold. First, it ensures the certificate has not expired. Second, it verifies that the identity contained within the certificate matches that of the remote party. More in-depth information on SSL callback functions can be found in the Platform SDK.

TCP/IP Registry Options
      Traditional TCP/IP stacks are developed to work efficiently on wired networks and do not address concerns introduced with wireless networks. Settings appropriate to Ethernet, for example, may waste bandwidth on wireless networks by unneeded retransmission requests. To improve efficiency, some TCP/IP parameters can be tuned to the characteristics of the supporting network. These parameters are maintained on a per-adapter basis, so applications must determine the appropriate adapter and change the associated parameter settings in the registry.
      Two parameters are most relevant: Receive Window Size and Initial Round Trip Time. The registry key for Receive Window Size is Adapter Name\tcpip\parms \TcpWindowSize. In general, larger receive windows work better with high-delay, high-bandwidth data. For added efficiency, the receive window should also be an even multiple of the TCP Maximum Segment Size (MSS) and should never exceed the system maximum, which has its own key (tcpip\parms\GlobalMaxTcpWindowSize). Currently there is a known problem with this parameter that will be fixed in a later release of Windows CE.
      The registry key for Initial Round Trip Time is Adapter Name\tcpip\parms\TcpInitialRTT. Round trip times are generally longer for wireless networks, and the recommended value is four seconds. If no value is set, the default is three seconds.

Conclusion
      Windows CE offers many exciting new capabilities in the world of mobile computing. The possible applications for this new operating system are limitless. Because it is a new technology, its specifications and capabilities are likely to change. A good place to find the latest Windows CE news is on the Microsoft Windows CE Web page at http://www.microsoft.com/windowsce). For programming information, consult the latest Platform SDK documentation.

From the May 1998 issue of Microsoft Systems Journal.