< I/O Completion Port Client-Server Example | Scalability Main | Chap 7: Socket Options & IOCTLs >


 

 

Scalable Winsock Applications 6 Part 4

 

 

What do we have in this chapter?

  1. The I/O Completion Port IPv4/IPv6 Server Program Example (continue)

 

 

The I/O Completion Port IPv4/IPv6 Server Program Example (continue)

 

 

Add the resolve.h header file.

 

The I/O Completion Port IPv4/IPv6 Server Program Example: Adding the resolve.h header file

 

Add the source code

 

// Common routines for resolving addresses and hostnames

// Files:

//      resolve.h       - Header file for common routines

// Description:

//      This file contains common name resolution and name printing

//      routines and is used by many of the samples.

//

#ifndef _RESOLVE_H_

#define _RESOLVE_H_

 

#ifdef _cplusplus

extern "C" {

#endif

 

int              PrintAddress(SOCKADDR *sa, int salen);

int              FormatAddress(SOCKADDR *sa, int salen, char *addrbuf, int addrbuflen);

struct addrinfo *ResolveAddress(char *addr, char *port, int af, int type, int proto);

 

#ifdef _cplusplus

}

#endif

 

#endif

 

Add the definition file, resolve.cpp for resolve.h header file

 

The I/O Completion Port IPv4/IPv6 Server Program Example: Adding the resolve.cpp definition file

 

Add the source code.

 

// Common routines for resolving addresses and hostnames

//

// Files:

//      resolve.cpp     - Common routines

//      resolve.h       - Header file for common routines

//

// Description:

//      This file contains common name resolution and name printing

//      routines and is used by many of the samples.

#include <winsock2.h>

#include <ws2tcpip.h>

#include <stdio.h>

#include <stdlib.h>

#include "resolve.h"

 

// Function: PrintAddress

// Description:

//    This routine takes a SOCKADDR structure and its length and prints

//    converts it to a string representation. This string is printed to the console via stdout.

int PrintAddress(SOCKADDR *sa, int salen)

{

    char    host[NI_MAXHOST], serv[NI_MAXSERV];

    int     hostlen = NI_MAXHOST, servlen = NI_MAXSERV, rc;

 

    rc = getnameinfo(sa, salen, host, hostlen, serv, servlen,NI_NUMERICHOST | NI_NUMERICSERV);

    if (rc != 0)

    {

        fprintf(stderr, "%s: getnameinfo() failed with error code %d\n", __FILE__, rc);

        return rc;

    }

    else

        printf("getnameinfo() is OK!\n");

 

    // If the port is zero then don't print it

    if (strcmp(serv, "0") != 0)

    {

        if (sa->sa_family == AF_INET)

            printf("[%s]:%s", host, serv);

        else

            printf("%s:%s", host, serv);

    }

    else

        printf("%s", host);

 

    return NO_ERROR;

}

 

// Function: FormatAddress

// Description:

//    This is similar to the PrintAddress function except that instead of

//    printing the string address to the console, it is formatted into the supplied string buffer.

int FormatAddress(SOCKADDR *sa, int salen, char *addrbuf, int addrbuflen)

{

    char    host[NI_MAXHOST], serv[NI_MAXSERV];

    int     hostlen = NI_MAXHOST, servlen = NI_MAXSERV, rc;

 

    rc = getnameinfo(sa, salen, host, hostlen, serv, servlen, NI_NUMERICHOST | NI_NUMERICSERV);

    if (rc != 0)

    {

        fprintf(stderr, "%s: getnameinfo() failed with error code %d\n", __FILE__, rc);

        return rc;

    }

    else

        printf("getnameinfo() is OK!\n");

 

    if ( (strlen(host) + strlen(serv) + 1) > (unsigned)addrbuflen)

        return WSAEFAULT;

    if (sa->sa_family == AF_INET)

        sprintf_s(addrbuf, sizeof(addrbuf), "%s:%s", host, serv);

    else if (sa->sa_family == AF_INET6)

        sprintf_s(addrbuf, sizeof(addrbuf), "[%s]:%s", host, serv);

    else

        addrbuf[0] = '\0';

 

    return NO_ERROR;

}

 

// Function: ResolveAddress

// Description:

//    This routine resolves the specified address and returns a list of addrinfo

//    structure containing SOCKADDR structures representing the resolved addresses.

//    Note that if 'addr' is non-NULL, then getaddrinfo will resolve it whether

//    it is a string literal address or a hostname.

struct addrinfo *ResolveAddress(char *addr, char *port, int af, int type, int proto)

{

    struct addrinfo hints, *res = NULL;

    int    rc;

 

    memset(&hints, 0, sizeof(hints));

    hints.ai_flags  = ((addr) ? 0 : AI_PASSIVE);

    hints.ai_family = af;

    hints.ai_socktype = type;

    hints.ai_protocol = proto;

 

    rc = getaddrinfo(addr, port, &hints, &res);

    if (rc != 0)

    {

        printf("Invalid address %s, getaddrinfo() failed with error code %d\n", addr, rc);

        return NULL;

    }

    else

        printf("getaddrinfo() should be fine!\n");

 

    return res;

}

 

Build and run the project.

 

The I/O Completion Port IPv4/IPv6 Server Program Example: Program sample output without any argument

 

Let test this program with the test client program created in the previous chapter. Firstly, run this server program.

 

The I/O Completion Port IPv4/IPv6 Server Program Example: Running the server listening to port 5151 for IPv4 and IPv6

 

Then run the client program several times with different –n values.

 

The I/O Completion Port IPv4/IPv6 Server Program Example: Running the client several times with different -n values

 

The server program sample output is shown below. It is very interesting if you can test this program in real network with many clients.

 

The I/O Completion Port IPv4/IPv6 Server Program Example: The server sample output after several client connections

 

 

 


< I/O Completion Port Client-Server Example | Scalability Main | Chap 7: Socket Options & IOCTLs >