This chapter is limited to describing how to make fundamental Winsock calls to set up communication using the Internet Protocol (IP) because most Winsock applications developed today use it because it is widely available due to the popularity of the Internet. However, Winsock is a protocol-independent interface. Also, our discussion of IP in this chapter is limited to briefly describing IP version 4 (IPv4). Throughout the remainder of this chapter, we will demonstrate the basics of how to set up Winsock communication using the IPv4 protocol. IP is widely available on most computer operating systems and can be used on most local area networks (LANs), such as a small network in your office, and on wide area networks (WANs), such as the Internet. By design, IP is a connectionless protocol and doesn't guarantee data delivery. Two higher-level protocols, Transmission Control Protocol (TCP) and User Datagram Protocol (UDP) are used for connection-oriented and connectionless data communication over IP, which we will describe later. Both TCP and UDP use IP for data transmission and are normally referred to as TCP/IP and UDP/IP. To use IPv4 in Winsock, you need understand how to address IPv4.
In IPv4, computers are assigned an address that is represented as a 32-bit quantity. When a client wants to communicate with a server through TCP or UDP, it must specify the server's IP address along with a service port number. Also, when servers want to listen for incoming client requests, they must specify an IP address and a port number. In Winsock, applications specify IP addresses and service port information through the SOCKADDR_IN structure, which is defined as:
struct sockaddr_in
{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
The sin_family field must be set to AF_INET, which tells Winsock we are using the IP address family.
The sin_port field defines which TCP or UDP communication port will be used to identify a server service. Applications should be particularly careful in choosing a port because some of the available port numbers are reserved for well-known services, such as File Transfer Protocol (FTP) and Hypertext Transfer Protocol (HTTP).
The sin_addr field of the SOCKADDR_IN structure is used for storing an IPv4 address as a four-byte quantity, which is an unsigned long integer data type. Depending on how this field is used, it can represent a local or a remote IP address. IP addresses are normally specified in Internet standard dotted notation as a.b.c.d. Each letter represents a number (in decimal, octal, or hexadecimal format) for each byte and is assigned, from left to right, to the four bytes of the unsigned long integer.
The final field, sin_zero, functions only as padding to make the SOCKADDR_IN structure the same size as the SOCKADDR structure.
A useful support function named inet_addr() converts a dotted IP address to a 32-bit unsigned long integer quantity. The inet_addr() function is defined as:
unsigned long inet_addr(const char FAR *cp);
The cp field is a null-terminated character string that accepts an IP address in dotted notation. Note that this function returns an IP address as a 32-bit unsigned long integer in network-byte order.
If no error occurs, inet_addr() returns an unsigned long value containing a suitable binary representation of the Internet address given. On Windows Server 2003 and later if the string in the cp parameter does not contain a legitimate Internet address, for example if a portion of an a.b.c.d address exceeds 255, then inet_addr() returns the value INADDR_NONE. This error is also returned if an empty string or NULL is passed in the cp parameter. On Windows XP and earlier if the string in the cp parameter does not contain a legitimate Internet address, for example if a portion of an a.b.c.d address exceeds 255, then inet_addr() returns the value INADDR_NONE. If the string in the cp parameter is an empty string or NULL, then inet_addr() returns the value INADDR_ANY.
The inet_addr() function interprets the character string specified by the cp parameter. This string represents a numeric Internet address expressed in the Internet standard .'' notation. The value returned is a number suitable for use as an Internet address. All Internet addresses are returned in IP's network order (bytes ordered from left to right). If you pass in (a space) to the inet_addr() function, inet_addr() returns zero.
On Windows Vista and later, the RtlIpv4StringToAddress() function can be used to convert a string representation of an IPv4 address to a binary IPv4 address represented as an IN_ADDR structure. While the RtlIpv6StringToAddress() function can be used to convert a string representation of an IPv6 address to a binary IPv6 address represented as an IN6_ADDR structure.
Values specified using the .'' notation takes one of the following forms:
When four parts are specified, each is interpreted as a byte of data and assigned, from left to right, to the 4 bytes of an Internet address. When an Internet address is viewed as a 32-bit integer quantity on the Intel architecture, the bytes referred to above appear as d.c.b.a''. That is, the bytes on an Intel processor are ordered from right to left. The parts that make up an address in . notation can be decimal, octal or hexadecimal as specified in the C language. Numbers that start with 0x or 0X imply hexadecimal. Numbers that start with 0 imply octal. All other numbers are interpreted as decimal.
Internet address value |
Meaning |
4.3.2.16 |
Decimal |
004.003.002.020 |
Octal |
0x4.0x3.0x2.0x10 |
Hexadecimal |
4.003.002.0x10 |
Mix |
The inet_addr() function supports the decimal, octal, hexadecimal, and mixed notations for the string passed in the cp parameter. The following para explains the notations which are only used by Berkeley software, and nowhere else on the Internet. For compatibility with Berkeley software, the inet_addr() function also supports the additional notations specified in the following paragraph. When a three-part address is specified, the last part is interpreted as a 16-bit quantity and placed in the right-most 2 bytes of the network address. This makes the three-part address format convenient for specifying Class B network addresses as 128.net.host''. When a two-part address is specified, the last part is interpreted as a 24-bit quantity and placed in the right-most 3 bytes of the network address. This makes the two-part address format convenient for specifying Class A network addresses as net.host''. When only one part is given, the value is stored directly in the network address without any byte rearrangement.