What do we have in this chapter?
Winsock Tutorial
Winsock: Story 1Winsock: Story 2Winsock: Story 3Winsock: Example 1Winsock: Example 2Winsock: Example 3Winsock: Example 4Winsock: Example 5Winsock: Example 6Winsock: Example 7Winsock: Example 8Winsock: Example 9Winsock: Example 10Winsock: Example 11Winsock: Example 12Winsock: Reference 1Winsock: Reference 2Winsock: Reference 3Winsock: Reference 4Another Complete and Advanced C & Winsock2 Programming Tutorial |
My Training Period: hours
Machine’s OS is standalone Windows Xp Pro with SP2 except whenever mentioned. Compiler used was Visual C++ 2003 .Net 1.1. Beware the codes that span more than one line. Program examples have been tested for Non Destructive Test. All information compiled for Windows 2000 (NT5.0) above and...
Abilities:
sockaddr Structure
|
||||||||||||||||
|
|
|||||||||||||||||
Except for the sinX_family parameter, sockaddr contents are expressed in network byte order.
SOCKADDR_STORAGE Structure
The SOCKADDR_STORAGE structure also stores socket address information and the structure is sufficiently large to store IPv4 or IPv6 address information. The use of the SOCKADDR_STORAGE structure promotes protocol-family and protocol-version independence, and simplifies development. It is recommended that the SOCKADDR_STORAGE structure be used in place of the sockaddr structure. The SOCKADDR_STORAGE structure is supported on Windows Server 2003 and later.
The SOCKADDR_STORAGE structure stores socket address information. Since the SOCKADDR_STORAGE structure is sufficiently large to store address information for IPv4, IPv6, or other address families, its use promotes protocol-family and protocol-version independence and simplifies cross-platform development. So, use the SOCKADDR_STORAGE structure in place of the sockaddr structure. The syntax for SOCKADDR_STORAGE is:
typedef struct sockaddr_storage {
short ss_family;
char __ss_pad1[_SS_PAD1SIZE];
__int64 __ss_align;
char __ss_pad2[_SS_PAD2SIZE];
} SOCKADDR_STORAGE,
*PSOCKADDR_STORAGE;
Members
ss_family - Address family of the socket, such as AF_INET. On Windows Vista and later, the datatype for this member is defined as an ADDRESS_FAMILY.
__ss_pad1 - Reserved. Defined as a 48-bit pad that ensures SOCKADDR_STORAGE achieves 64-bit alignment.
__ss_align - Reserved. Used by the compiler to align the structure.
__ss_pad2 - Reserved. Used by the compiler to align the structure.
Keep in mind that in the Microsoft Windows Software Development Kit (SDK), the version of this structure for use on Windows Vista and later is defined as SOCKADDR_STORAGE_LH. In the Windows SDK, the version of this structure to be used on earlier systems including Windows XP and later is defined as SOCKADDR_STORAGE_XP. When compiling an application if the target platform is Windows Vista and later (NTDDI_VERSION >= NTDDI_LONGHORN, _WIN32_WINNT >= 0x0600, or WINVER >= 0x0600), the SOCKADDR_STORAGE_LH structure is typedefed to the SOCKADDR_STORAGE structure. When compiling an application if the target platform is not Windows Vista and later, the SOCKADDR_STORAGE_XP structure is typedefed to the SOCKADDR_STORAGE structure. The SOCKADDR_STORAGE_LH structure defines the data type of first member of the structure as an ADDRESS_FAMILY.Application developers normally use only the ss_family member of the SOCKADDR_STORAGE. The remaining members ensure that the SOCKADDR_STORAGE can contain either an IPv6 or IPv4 address and the structure is padded appropriately to achieve 64-bit alignment. Such alignment enables protocol-specific socket address data structures to access fields within a SOCKADDR_STORAGE structure without alignment problems. With its padding, the SOCKADDR_STORAGE structure is 128 bytes in length. The first member field of the SOCKADDR_STORAGE structure is isomorphic with the sockaddr structure to enable a simplified transition from the sockaddr structure to the SOCKADDR_STORAGE structure. For more information about platform-independent SOCKADDR_STORAGE implementation recommendations, refer to RFC 2553, available at www.ietf.org.On the Windows SDK released for Windows Vista and later, the organization of header files has changed and the SOCKADDR_STORAGE structure is defined in the Ws2def.h header file. Note that the Ws2def.h header file is automatically included in Winsock2.h, and should never be used directly.
Program Example Using sockaddr
The following example demonstrates the use of the sockaddr structure.
#include <stdio.h>
#include "winsock2.h"
int main()
{
// Declare variables
WSADATA wsaData;
SOCKET ListenSocket;
sockaddr_in service;
// Initialize Winsock, request the Winsock 2.2
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != NO_ERROR)
printf("Error at WSAStartup().\n");
else
printf("WSAStartup() is OK.\n");
// Create a listening socket
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET)
{
printf("Error at socket().\n");
WSACleanup();
return 0;
}
else
printf("socket() is OK.\n");
// Bind the socket to the local IP address and port 55555
hostent* thisHost;
char* ip;
u_short port;
port = 55555;
thisHost = gethostbyname("");
ip = inet_ntoa(*(struct in_addr *)*thisHost->h_addr_list);
printf("\nIP address is: %s.\n", ip);
printf("Hostname is: %s.\n", thisHost->h_name);
printf("Address type: %i.\n\n", thisHost->h_addrtype);
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(port);
if (bind(ListenSocket,(SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
printf("bind() failed lol!\n");
closesocket(ListenSocket);
return 0;
}
else
printf("bind() is OK.\n");
WSACleanup();
return 0;
}
Sample output:
---------------------------------------------

Figure 1
hostent Structure
|
Item |
Description |
|
Structure |
hostent |
|
Info |
Used by functions to store information about a given host, such as host name, IP address, and so forth. An application should never attempt to modify this structure or to free any of its components. Furthermore, only one copy of the hostent structure is allocated per thread, and an application should therefore copy any information that it needs before issuing any other Windows Sockets API calls. |
|
Definition |
typedef struct hostent { char FAR* h_name; char FAR FAR** h_aliases; short h_addrtype; short h_length; char FAR FAR** h_addr_list; } hostent; |
|
Members |
h_name - Official name of the host (PC). If using the DNS or similar resolution system, it is the Fully Qualified Domain Name (FQDN) that caused the server to return a reply. If using a local hosts file, it is the first entry after the IP address. h_aliases - Null-terminated array of alternate names. h_addrtype - Type of address being returned. h_length - Length of each address, in bytes. h_addr_list - Null-terminated list of addresses for the host. Addresses are returned in network byte order. The macro h_addr is defined to be h_addr_list[0] for compatibility with older software. |
|
Header file |
<winsock2.h> |
|
Remark |
- |
|
Table 2 |
|
gethostbyaddr()
|
Item |
Description |
|
Function |
gethostbyaddr() |
|
Use |
Retrieves the host information corresponding to a network address. The gethostbyaddr function has been deprecated by the introduction of the getnameinfo() function. Developers creating Windows Sockets 2 applications are urged to use the getnameinfo() function instead of the gethostbyaddr() function. |
|
Prototype |
struct HOSTENT* FAR gethostbyaddr( const char* addr, int len, int type); |
|
Parameters |
addr - [in] Pointer to an address in network byte order. len - [in] Length of the address, in bytes. type - [in] Type of the address, such as the AF_INET address family type (defined as TCP, UDP, and other associated Internet protocols). Address family types and their corresponding values are defined in the winsock2.h header file. |
|
Return value |
See below. |
|
Include file |
<winsock2.h> |
|
Library |
ws2_32.lib. |
|
Remark |
The gethostbyaddr() function returns a pointer to the hostent structure that contains the name and address corresponding to the given network address. Although gethostbyaddr is deprecated by the getnameinfo() function, gethostbyaddr is capable of returning a NetBIOS name; getnameinfo is not. Developers requiring NetBIOS name resolution may need to use gethostbyaddr() until their applications are completely independent of NetBIOS names. Note The capability to perform reverse lookups using the gethostbyaddr function is convenient, but such lookups are considered inherently unreliable, and should be used only as a hint. |
|
Table 3 |
|
Return Values
If no error occurs, gethostbyaddr() returns a pointer to the hostent structure. Otherwise, it returns a null pointer, and a specific error code can be retrieved by calling WSAGetLastError().
|
Error code |
Meaning |
WSANOTINITIALISED |
A successful WSAStartup() call must occur before using this function. |
WSAENETDOWN |
The network subsystem has failed. |
WSAHOST_NOT_FOUND |
Authoritative answer host not found. |
WSATRY_AGAIN |
Non-authoritative host not found, or server failed. |
WSANO_RECOVERY |
A non-recoverable error occurred. |
WSANO_DATA |
Valid name, no data record of requested type. |
WSAEINPROGRESS |
A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. |
WSAEAFNOSUPPORT |
The type specified is not supported by the Windows Sockets implementation. |
WSAEFAULT |
The addr parameter is not a valid part of the user address space, or the len parameter is too small. |
WSAEINTR |
A blocking Windows Socket 1.1 call was canceled through WSACancelBlockingCall(). |
|
Table 4 |
|
For program sample, see the following example.
gethostbyname()
|
Item |
Description |
|
Function |
gethostbyname(). |
|
Use |
Retrieves host information corresponding to a host name from a host database. The gethostbyname() function has been deprecated by the introduction of the getaddrinfo() function. Developers creating Windows Sockets 2 applications are urged to use the getaddrinfo() function instead of gethostbyname(). |
|
Prototype |
struct hostent* FAR gethostbyname(const char* name); |
|
Parameters |
name - [in] Pointer to the null-terminated name of the host to resolve. |
|
Return value |
See below. |
|
Include file |
<winsock2.h> |
|
Library |
ws2_32.lib. |
|
Remark |
The gethostbyname() function returns a pointer to a hostent structure - a structure allocated by Windows Sockets. The hostent structure contains the results of a successful search for the host specified in the name parameter. The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, so the application should copy any information it needs before issuing any other Windows Sockets function calls. The gethostbyname() function cannot resolve IP address strings passed to it. Such a request is treated exactly as if an unknown host name were passed. Use inet_addr to convert an IP address string the string to an actual IP address, then use another function, gethostbyaddr(), to obtain the contents of the hostent structure. If null is provided in the name parameter, the returned string is the same as the string returned by a successful gethostname() function call. The gethostbyname() function does not check the size of the name parameter before passing the buffer. In improperly sized name parameters, heap corruption can occur. |
|
Table 5 |
|
Return Values
If no error occurs, gethostbyname() returns a pointer to the hostent structure described above. Otherwise, it returns a null pointer and a specific error number can be retrieved by calling WSAGetLastError().
|
Error code |
Meaning |
WSANOTINITIALISED |
A successful WSAStartup() call must occur before using this function. |
WSAENETDOWN |
The network subsystem has failed. |
WSAHOST_NOT_FOUND |
Authoritative answer host not found. |
WSATRY_AGAIN |
Non-authoritative host not found, or server failure. |
WSANO_RECOVERY |
A non-recoverable error occurred. |
WSANO_DATA |
Valid name, no data record of requested type. |
WSAEINPROGRESS |
A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. |
WSAEFAULT |
The name parameter is not a valid part of the user address space. |
WSAEINTR |
A blocking Windows Socket 1.1 call was canceled through WSACancelBlockingCall(). |
|
Table 6 |
|
gethostbyname() and gethostbyaddr() Program Example
The following examples demonstrates the use of the gethostbyname() and gethostbyaddr() functions.
#include <stdio.h>
#include <winsock2.h>
int main()
{
// Declare variables
WSADATA wsaData;
// Initialize Winsock, request the Winsock 2.2
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != NO_ERROR)
printf("Error at WSAStartup().\n");
else
printf("WSAStartup() is OK.\n");
// Declare and initialize variables
hostent* remoteHost;
char* ip;
char* host_name;
unsigned int addr;
// User inputs name of host
printf("Input name/IP of host: ");
host_name = (char*) malloc(sizeof(char*)*128);
fgets(host_name, 128, stdin);
// If the user input is an alpha name for the host, use gethostbyname()
// else, gethostbyaddr() (assume IPv4) host address is a name
if (isalpha(host_name[0]))
{
printf("\nUsing gethostbyname()...\n");
// NULL terminated
host_name[strlen(host_name)-1] = '\0';
remoteHost = gethostbyname(host_name);
ip = inet_ntoa(*(struct in_addr *)*remoteHost->h_addr_list);
printf("IP address is: %s.\n", ip);
printf("Address type: %i.\n\n", remoteHost->h_addrtype);
}
else
{
printf("\nUsing gethostbyaddr()...\n");
addr = inet_addr(host_name);
remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
printf("Hostname is: %s.\n", remoteHost->h_name);
printf("Address type: %i.\n\n", remoteHost->h_addrtype);
}
if (WSAGetLastError() != 0)
{
if (WSAGetLastError() == 11001)
printf("Host not found...\nExiting.\n");
}
else
printf("error #: %ld\n", WSAGetLastError());
// The remoteHost structure can now be used to access information about the host
WSACleanup();
return 0;
}
Sample output:

Figure 2

Figure 3
Further reading and digging:
Linux Sockets: Story and program examples.
Structure, enum, union and typedef story can be found struct, enum, union & typedef tutorial.
For Multibytes, Unicode characters and Localization please refer to Multibyte, Unicode and wide characters (Story) and Win32 Windows & Users tutorial (Implementation).
Windows data type information is Win32 - Windows data types.
A complete info on Windows socket reference from MSDN which include managed and unmanaged API doc.
Check the best selling C / C++ and Windows books at Amazon.com.