Monday, December 10, 2007

Winsock

A Quick Look at TCP/IP
To better understand how Winsock works on Pocket PC, it is important to understand how TCP/IP itself is constructed. As mentioned previously, TCP/IP stands for Transmission Control Protocol/Internet Protocol, which typically represents the Internet Protocol Suite. The TCP/IP protocol suite is actually a collection of several protocols that form the basis of Internet communications. Table 1.1 describes the TCP/IP protocol suite.

Table 1.1. The TCP/IP Protocol Suite Protocol
Usage

IP
The Internet Protocol is responsible for the addressing, routing and packetization of data. It basically moves data between computers.

TCP
The Transport Control Protocol is a reliable connection—based data transport.

UDP
The User Datagram Protocol is a connectionless-based data transport that does not guarantee packets will arrive at their destination.

ICMP
The Internet Control Message Protocol handles error and control messages.

ARP
The Address Resolution Protocol performs IP address to hardware address translation for outgoing packets.



Developing applications that use Winsock on a Pocket PC device will require you to work with and understand the various TCP/IP protocols in order to effectively use networking in your application.

A Breakdown of TCP/IP
When you look at the various parts of TCP/IP, it is typically represented in the International Standards Organization/Open Systems Interconnect (ISO/OSI) network model, which divides networks into various layers depending on individual functionality (see Figure 1.1). The combination of each layer provides what is commonly known as the TCP/IP protocol stack. Note that the data-link layer and the physical layer are not technically part of the Internet Protocol Suite; this is what enables TCP/IP to talk over a variety of network types and mediums.

Figure 1.1. The ISO/OSI model


Let's take a quick look at each of the layers:


Physical: The physical layer is essentially the network hardware. This layer talks directly to the media (wireless, twisted pair cable, and so on) that is carrying the network data.



Data Link: The data-link layer (which is sometimes also called the network driver layer) manages requests to the network interface, and transfers data between the physical and network layers. Most importantly, it also hides the network's physical implementation from the network layer. This ensures that the protocol (in our case, TCP/IP) doesn't care about the specifics of what network technology is being used (such as Ethernet versus WiFi)—it simply passes data back and forth.



Network: The network layer is the core of TCP/IP. It is responsible for the addressing, routing, and packetization of data that it has received from the transport layer over the Internet Protocol (IP), and for passing it to the data-link layer. The network layer also provides the mapping of IP addresses to hardware addresses via the Address Resolution Protocol (ARP); the processing of error and control messages through the Internet Control Message Protocol (ICMP); and the control of multicast communications through the Internet Group Membership Protocol (IGMP).



Transport: The transport layer is what applications will typically talk to when running Winsock applications, and is sometimes called a low-level connection. It provides the transfer of data between a source and destination on the network. Pocket PC supports two transfer protocols: the Transfer Control Protocol (TCP) and the User Datagram Protocol (UDP). TCP is a connection-based protocol that reliably streams data from source to destination, whereas UDP is an unreliable, connectionless protocol that uses packets to send data from point A to point B.



Session: The session layer essentially creates a connection, controls it, and then finally closes the communications session. It is also sometimes referred to as a high-level connection, and it starts the upper layer of the OSI model. A session is usually defined by a specific application protocol, such as Telnet, for establishing and maintaining a connection between a client and a server.



Presentation: The presentation layer basically handles the formatting of data that two applications will use during the course of a session. Transfer protocols, such as FTP, SMTP, and HTTP, are considered part of the presentation layer.



Application: The application layer is what interacts with the user. It is the user interface for your application.


TCP/IP Addresses
In order for a device to talk on a TCP/IP network, it needs a valid network "address." TCP/IP on Pocket PC currently supports IP version 4 (IPv4), whereby network addresses are represented as a 32-bit number, which can be broken down into a host address and a subnet address. Typically, a user can recognize an IPv4 address by what's more commonly known as dotted notation, such as 192.168.0.1.

You should be aware of the following address types:

Unicast Address: A unicast address is typically what is assigned to your device, either through a hard-coded IP address, or one that is assigned to you via a DHCP server. This is the unique address that is used to identify your device on a network.

Broadcast Address: While not recommended, if you need to broadcast data to every device on a local network, you can send data to the address 255.255.255.255. Sending data here is considered a limited broadcast because most routers will never forward packets sent to this address. A directed broadcast address can also be used to send data to all devices on a specific subnet, such as 192.168.0.x, by sending data to 192.168.0.255. In order send data packets over a broadcast address, you need to set a socket option to accept broadcast communications, as well as use the UDP protocol as described later in the section "Connectionless (UDP) Sockets."

Loopback Address: Any network address that begins with the number 127 is considered a loopback address for the device. Typically, the address 127.0.0.1 is used to communicate with itself.

Multicast Address: The best way to think of a multicast address is to think of a "group" address. When you are a part of a multicast group, all of the devices that have joined that group will receive data that is sent to the group address. Multicast groups use a reserved address range from 224.0.0.0 through 239.255.255.255.

Whenever a Winsock function requires a TCP/IP address, it is specified by using the SOCKADDR_IN structure, which is defined as follows:

struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};

The sin_family parameter represents the address family, and must be set to AF_INET to use IP addressing (AF_IRDA is available for infrared, which is covered in Chapter 5). The next parameter, sin_port, specifies the communications port that you want your protocol, whether TCP or UDP, to talk on. The port typically represents a well-known service, such as HTTP or FTP. The sin_addr parameter specifies the IP address and can be either a local address or a remote address, depending on how the field is being used by the Winsock operation. The last parameter, sin_zero, is unused and serves as padding for the standard SOCKADDR structure.

Ports
As mentioned above, a TCP/IP port represents a specific communications port used by an application protocol to identify a service, such as HTTP or FTP. While you can certainly use any port for your own application, take care not to use the ones that are already defined by the Internet Assigned Numbers Authority (IANA), which are known as well-known ports (see Table 1.2).

Table 1.2. Well-Known Ports Protocol
Port

File Transfer Protocol (FTP)
21

Telnet Protocol
23

Simple Mail Transfer Protocol (SMTP)
25

Trivial File Transfer Protocol (TFTP)
69

Gopher Protocol
70

Finger Protocol
79

Hypertext Transfer Protocol (HTTP)
80

Post Office Protocol (POP3)
110



A list of up-to-date assigned port numbers is available at http://www.iana.org/assignments/port-numbers.

Ports are divided into three basic categories:

Well-known ports (0–1023): These are controlled by the IANA and are reserved for well-known ports.

Registered ports (1024–49151): These ports are listed and controlled by IANA, but they can also be used for normal applications.

Dynamic or private ports (49152–65535): The IANA does not track any applications that use ports in this range.

Therefore, for example, if you are writing an application that needs to read data from a Web server, you will use the well-known port 80. If you need to develop a custom application, it is safe for you to use any port in the range of 1024–49151.

If you are interested in more in-depth details about TCP/IP, IP addressing, and TCP/IP ports, I highly recommend that you read RFC 1180, "A TCP/IP Tutorial," and RFC 1122, "Requirements for Internet Hosts—Communication Layers."



Winsock Basics
Now that we have covered the basics of TCP/IP, let's look at actual Winsock APIs that your application will use to communicate over the network with. To use the Winsock functions in your applications, make sure you include winsock.h in your source, and that you link with the winsock.lib library.

Initializing and Cleaning Up
The first thing to do in order to use Winsock is to make sure that the correct version of winsock.dll is loaded into memory. Even though Pocket PC currently supports only a subset of Winsock version 1.1, it still needs to be initialized in the same way as its desktop counterpart before it is used. This is done by calling the WSAStartup() function, which is defined as follows:

int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);

The wVersionRequired parameter specifies which version of Winsock you want to load. For Pocket PC, this value needs to be version 1.1, which can be created by using the MAKEWORD(1,1) macro. The lpWSAData parameter is a pointer to a WSAData structure that WSAStartup() will fill in with information about the version of Winsock that is loaded:

typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR *lpVendorInfo;
} WSADATA;

Both the wVersion and wHighVersion parameters will return the current version of Winsock that is actually loaded into memory, which will be 0x0101, as only 1.1 is supported. The szDescription and szSystemStatus parameters are not used on Pocket PC and are NULL. The iMaxSockets parameter indicates the recommended maximum number of sockets that an application can actually open. There is no guarantee that your application will be able to open this many sockets. The iMaxUdpDg parameter specifies the largest size of a UDP datagram packet. If this value is 0, there is no limit in this Winsock version. Finally, the lpVendorInfo parameter has a pointer to optional vendor-specific information.

WSAStartup() will return 0 if it succeeds; otherwise, it will return an error code.

Before your application closes, you should call the function WSACleanup(), which is defined as follows:

int WSACleanup(void);

However, note that this function doesn't actually do anything, and is there only to maintain compatibility with desktop applications that have been ported to Windows CE.

Winsock Errors
If an error occurs when calling a Winsock function (except WSAStartup(), which will return an error code), most functions will return the standard Winsock SOCKET_ERROR (defined in winsock.h as -1).

To obtain more information about the error that occurred, you can call the function WSAGetLastError() to find out why the function failed:

int WSAGetLastError (void);

The return value will be the error code for the last network error that occurred. If you need to set the last error for any reason (or to set it to 0), you can use the function WSASetLastError():

void WSASetLastError (int iError);

The parameter iError specifies the new error code.

You can find definitions for the individual Winsock error codes in the winsock.h header file.

Differences between Windows and Pocket PC Winsock Implementations
Besides the fact that Pocket PC supports only a subset of Winsock version 1.1, note a few other minor differences compared to the desktop implementation:

There are no asynchronous socket calls. There is no support in Pocket PC for desktop function calls such as WSAAsyncSelect() for notification of socket events.

There are no service name APIs. The desktop functions getservbyname() and getservbyport() are not supported on Pocket PC.

There are no protocol name APIs. The desktop functions getprotobyname() and getprotobynumber() are not supported on Pocket PC.

Unicode and ASCII. Although data that you send over TCP (and UDP messages) can be Unicode or ASCII (Winsock doesn't care, as long as corresponding support exists on both ends and everything is handled properly), most of the Winsock support functions support ASCII parameters only. You need to convert the Unicode strings to ASCII to use them.

Blocking versus nonblocking. Sockets are in blocking mode by default. You can set a socket to nonblocking mode by setting the correct socket option, as described in the section "Socket Options."

Several socket options are not supported. IP_MULTICAST_LOOP, SO_ACCEPTCONN, SO_RCVLOWAT, SO_SNDLOWAT, SO_SNDTIMEO, and the SO_TYPE socket options are not supported on Pocket PC.

IrDA supports only TCP stream sockets. Infrared communication via Winsock (covered in Chapter 5) supports using TCP sockets only.

Applications can drop UDP packets. The internal UDP queue buffer size is set to 2. This is a known bug and is documented in Microsoft KB article Q290206.

No raw socket support. There currently is no way to create a raw socket. However, you can use the ICMP support functions described in the section "Internet Control Message Protocol (ICMP)" to send ping data.

Finally, note that Windows CE.NET (Windows CE v4.x) now supports Winsock v2.0.

TCP/IP, ActiveSync, and Pocket PC Emulation Issues
While TCP/IP communications are a great way of enabling a Pocket PC device to network with a desktop, a server, or another Pocket PC device, accessing incoming TCP/IP connections can sometimes be a bit tricky if you are not using a network card or a wireless connection. This is typically true during development stages, when devices are often cradled to a desktop and you use the emulation environment.

Neither the emulator nor the device should have any problems establishing connections to a TCP/IP server (in essence, when the device/emulation is acting as a client or initiating a connection), but external resources will not be able to find the device when the device/emulation itself is waiting for incoming connections (i.e., it's acting as a server).

These problems are caused by the way IP addresses are assigned. The emulator uses a private IP address, and ActiveSync uses a Network Address Table (NAT) for cradled communications. Both render it unreachable from the outside world. You can, however, use the "localhost" address on the device itself to establish a connection within the device. For example, if you are writing an application to respond to HTTP requests, and the application is running in the emulation environment, you could use Pocket Internet Explorer inside the emulator to go to http://localhost to access your server.

This should not affect your device when using a dial-up connection, a wireless connection, or a network card.

No comments: