IP

The Internet Protocol (IP) is commonly known as the network protocol that is used on the Internet. 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 delivery of data. Two higher-level protocols—TCP and UDP—are used for data communication over IP.

TCP

Connection-oriented communication is accomplished through the Transmission Control Protocol (TCP). TCP provides reliable error-free data transmission between two computers. When applications communicate using TCP, a virtual connection is established between the source computer and the destination computer. Once a connection is established, data can be exchanged between the computers as a two-way stream of bytes.

UDP

Connectionless communication is accomplished through the User Datagram Protocol (UDP). UDP doesn't guarantee reliable data transmission and is capable of sending data to multiple destinations and receiving data from multiple sources. For example, if a client sends data to a server, the data is transmitted immediately, whether or not the server is ready to receive the data. If the server receives data from the client, it doesn't acknowledge the receipt. Data is transmitted using datagrams.

Both TCP and UDP use IP for data transmission and are normally referred to as TCP/IP and UDP/IP. Winsock addresses IP communication through the AF_INET address family, which is defined in Winsock.h and Winsock2.h.

Addressing

In IP, computers are assigned an IP address that is represented as a 32-bit quantity, formally known as an IP version 4 (IPv4) address. 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.

IP Version 6
IP version 6 is an updated specification of IP that allows for a larger address space, which will become necessary in the near future, as IP version 4 addresses become scarce. Many of the Winsock header files contain conditional definitions for IPv6 structures; however, no current Win32 platform provides an IPv6 network stack (including Windows 2000). Microsoft Research has made available an experimental IPv6 stack that you can download and use (http://research.microsoft.com/msripv6/); however, it isn't supported, and we do not address any version 6-specific issues in this text.

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 ports used by well-known services are controlled and assigned by the Internet Assigned Numbers Authority (IANA) and are described in RFC 1700. Essentially, the port numbers are divided into the three ranges explained below: well-known, registered, and dynamic and/or private ports.

  • 0-1023 are controlled by the IANA and are reserved for well-known services.
  • 1024-49151 are registered ports listed by the IANA and can be used by ordinary user processes or programs executed by ordinary users.
  • 49152-65535 are dynamic and/or private ports.

Ordinary user applications should choose the registered ports in the range 1024-49151 to avoid the possibility of using a port already in use by another application or a system service. Ports in the range 49152-65535 can also be used freely because no services are registered on these ports with the IANA. If, when using the bind API function, your application binds to a port that is already in use by another application on your host, the system will return the Winsock error WSAEADDRINUSE. Chapter 7 describes the Winsock bind process in greater detail.

The sin_addr field of the SOCKADDR_IN structure is used for storing an IP address as a 4-byte quantity, which is an unsigned long integer data type. Depending on how this field is used, it can represent a local or remote IP address. IP addresses are normally specified in Internet standard dotted notation as "a.b.c.d." Each letter represents a number 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. (Network-byte order is described shortly, under "Byte ordering.")

Special addresses

Two special IP addresses affect the behavior of a socket in certain situations. The special address INADDR_ANY allows a server application to listen for client activity over every network interface on a host computer. Typically, server applications use this address when they bind a socket to the local interface to listen for connections. If you have a multihomed system, this address allows a single application to accept responses from multiple interfaces.

The special address INADDR_BROADCAST can be used to send broadcast UDP datagrams over an IP network. Using this special address requires an application to set the socket option SO_BROADCAST. Chapter 9 explains this option in greater detail.

Byte ordering

Different computer processors represent numbers in big-endian and little-endian form, depending on how they are designed. For example, on Intel x86 processors, multibyte numbers are represented in little-endian form: the bytes are ordered from least significant byte to most significant byte. When an IP address and port number are specified as multibyte quantities in a computer, they are represented in host-byte order. However, when IP addresses and port numbers are specified over a network, Internet networking standards specify that multibyte values must be represented in big-endian form (most significant byte to least significant byte), normally referred to as network-byte order.

A series of functions can be used to convert a multibyte number from host-byte order to network-byte order and vice versa. The following four API functions convert a number from host-byte to network-byte order:

 u_long htonl(u_long hostlong); int WSAHtonl( SOCKET s, u_long hostlong, u_long FAR * lpnetlong ); u_short htons(u_short hostshort); int WSAHtons( SOCKET s, u_short hostshort, u_short FAR * lpnetshort ); 

The hostlong parameter of htonl and WSAHtonl is a 4-byte number in host-byte order. The htonl function returns the number in network-byte order, whereas the WSAHtonl function returns the number in network-byte order through the lpnetlong parameter. The hostshort parameter of htons and WSAHtons is a 2-byte number in host-byte order. The htons function returns the number as a 2-byte value in network-byte order, whereas the WSAHtons function returns the number through the lpnetshort parameter.

The next four functions are the opposite of the preceding four functions: they convert from network-byte order to host-byte order.

 u_long ntohl(u_long netlong); int WSANtohl( SOCKET s, u_long netlong, u_long FAR * lphostlong ); u_short ntohs(u_short netshort); int WSANtohs( SOCKET s, u_short netshort, u_short FAR * lphostshort ); 

We will now demonstrate how to create a SOCKADDR_IN structure using the inet_addr and htons functions described above.

 SOCKADDR_IN InternetAddr; INT nPortId = 5150; InternetAddr.sin_family = AF_INET; // Convert the proposed dotted Internet address 136.149.3.29 // to a 4-byte integer, and assign it to sin_addr InternetAddr.sin_addr.s_addr = inet_addr("136.149.3.29"); // The nPortId variable is stored in host-byte order. Convert // nPortId to network-byte order, and assign it to sin_port. InternetAddr.sin_port = htons(nPortId); 

Now that you have the basics of addressing IP through a SOCKADDR_IN structure, you can prepare to set up communication for TCP or UDP by creating a socket.

Creating a Socket

Creating an IP socket offers applications the capability to communicate over the TCP, UDP, and IP protocols. To open an IP socket using the TCP protocol, call the socket function or the WSASocket function with the address family AF_INET and the socket type SOCK_STREAM, and set the protocol field to 0, as follows:

 s = socket(AF_INET, SOCK_STREAM, 0); s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); 

To open an IP socket using the UDP protocol, simply specify the socket type SOCK_DGRAM instead of SOCK_STREAM in the socket and WSASocket calls above. It is also possible to open a socket to communicate directly over IP. This is accomplished by setting the socket type to SOCK_RAW. Chapter 13 describes the SOCK_RAW option in greater detail.

Name Resolution

When a Winsock application wants to communicate with a host over IP, it must know the host's IP address. From an application user's point of view, IP addresses aren't easy to remember. Most people would much rather refer to a machine by using an easy-to-remember, user-friendly host name instead of an IP address. Winsock provides two support functions that can help you resolve a host name to an IP address.

The Windows Sockets gethostbyname and WSAAsyncGetHostByName API functions retrieve host information corresponding to a host name from a host database. Both functions return a HOSTENT structure that is defined as

 struct hostent { char FAR * h_name; char FAR * FAR * h_aliases; short h_addrtype; short h_length; char FAR * FAR * h_addr_list; }; 

The h_name field is the official name of the host. If your network uses the Domain Name System (DNS), it is the Fully Qualified Domain Name (FQDN) that causes the name server to return a reply. If your network uses a local "hosts" file, it is the first entry after the IP address. The h_aliases field is a null-terminated array of alternative names for the host. The h_addrtype represents the address family being returned. The h_length field defines the length in bytes of each address in the h_addr_list field. The h_addr_list field is a null-terminated array of IP addresses for the host. (A host can have more than one IP address assigned to it.) Each address in the array is returned in network-byte order. Normally, applications use the first address in the array. However, if more than one address is returned, applications should randomly choose an available address rather than always use the first address.

The gethostbyname API function is defined as

 struct hostent FAR * gethostbyname ( const char FAR *  name    ); 

The name parameter represents a friendly name of the host you are looking for. If this function succeeds, a pointer to a HOSTENT structure is returned. Note that the memory where the HOSTENT structure is stored is system memory. An application shouldn't rely on this to remain static. Since this memory is maintained by the system, your application doesn't have to free the returned structure.

The WSAAsyncGetHostByName API function is an asynchronous version of the gethostbyname function that uses Windows messages to inform an application when this function completes. WSAAsyncGetHostByName is defined as

 HANDLE WSAAsyncGetHostByName( HWND hWnd, unsigned int wMsg, const char FAR * name, char FAR * buf, int buflen ); 

The hWnd parameter is the handle of the window that will receive a message when the asynchronous request completes. The wMsg parameter is the Windows message to be received when the asynchronous request completes. The name parameter represents a user-friendly name of the host we are looking for. The buf parameter is a pointer to the data area to receive the HOSTENT data. This buffer must be larger than a HOSTENT structure and should be set to the size defined in MAXGETHOSTSTRUCT.

Two more functions that retrieve host information are worth mentioning: the gethostbyaddr and WSAAsyncGetHostByAddr API functions, which are designed to retrieve host information corresponding to an IP network address. These functions are useful when you have the IP address of a host and want to look up its user-friendly name. The gethostbyaddr function is defined as

 struct HOSTENT FAR * gethostbyaddr( const char FAR * addr, int len, int type ); 

The addr parameter is a pointer to an IP address in network-byte order. The len parameter specifies the byte length of the addr parameter. The type parameter should specify the value AF_INET, which indicates that this is an IP address type. The WSAAsyncGetHostByAddr API function is an asynchronous version of gethostbyaddr.

Port numbers

In addition to the IP address of a remote computer, an application must know the service's port number to communicate with a service running on a local or remote computer. When using TCP and UDP, applications must decide which ports they plan to communicate over. There are well-known port numbers reserved by server services that support protocols of a level higher than TCP. For example, port 21 is reserved for FTP, and port 80 is reserved for HTTP. As mentioned earlier, well-known services typically use ports 1-1023 to set up communication. If you are developing a TCP application that doesn't use one of the well-known services, consider using ports above 1023 to avoid using a port already being used. You can retrieve port numbers for well-known services by calling the getservbyname and WSAAsyncGetServByName functions. These functions simply retrieve static information from a file named services. In Windows 95 and Windows 98, the services file is located under %WINDOWS%; and in Windows NT and Windows 2000, it is located under %WINDOWS%\System32\Drivers\Etc. The getservbyname function is defined as follows:

 struct servent FAR * getservbyname( const char FAR * name, const char FAR * proto ); 

The name parameter represents the name of the service you are looking for. For example, if you are trying to locate the port for FTP, you should set the name parameter to point to the string "ftp." The proto parameter optionally points to a string that indicates the protocol that the service in name is registered under. The WSAAsyncGetServByName function is an asynchronous version of getservbyname.

Windows 2000 has a new dynamic method to register and query service information for TCP and UDP. Server applications can register the service name, IP address, and port number of a service by using the WSASetService function. Client applications can query this service information by using a combination of the following API functions: WSALookupServiceBegin, WSALookupServiceNext, and WSALookupServiceEnd. Chapter 10 covers the details of using these capabilities.



Network Programming for Microsoft Windows
Linux Server Hacks, Volume Two: Tips & Tools for Connecting, Monitoring, and Troubleshooting
ISBN: 735615799
EAN: 2147483647
Year: 1998
Pages: 159

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net