⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resolver.cpp

📁 < WINDOWS网络编程>>英文版,一本详细讲解WINDOWS平台下网络编程的国外经典书籍,适合英文水平高的牛人
💻 CPP
字号:
//
// Sample: Illustrates getaddrinfo and getnameinfo
//
// Files:
//      resolver.cpp        - this file
//
// Description:
//      This sample illustrates how to use the new name resolution APIs:
//      getaddrinfo and getnameinfo. This sample takes a hostname or address
//      and performs an address resolution via getaddrinfo. This lookup will
//      return one or more binary addresses which will then be passed to
//      getnameinfo to perform a reverse lookup. The results of each query
//      are displayed to the console.
//
// Complile:
//      cl.exe -o resolver.exe resolver.cpp ws2_32.lib
//
// Usage:
//   resolver.exe [options]
//      -n name            Host name to resolve
//      -s port/service    Service name or port number to resolve
//      -a address-family  Preferred address family
//         4                   IPv4 (AF_INET)
//         6                   IPv6 (AF_INET6)
//      -t socket-type     Preferred socket type
//         stream              Stream socket (SOCK_STREAM)
//         dgram               Datagram socket (SOCK_DGRAM)
//      -p protocol        Preferred protocol
//         tcp                 TCP (IPPROTO_TCP)
//         udp                 UDP (IPPROTO_UDP)
//      -f flag            Flags passed to getname info (options may be present multiple times)
//         nofqdn               NI_NOFQDN
//         numerichost          NI_NUMERICHOST
//         namereqd             NI_NAMEREQD
//         numericserv          NI_NUMERICSERV
//         dgram                NI_DGRAM
//      -b                 Obtain the bind address for the given address family (i.e. AI_PASSIVE)
//

#include <winsock2.h>
#include <ws2tcpip.h>

// If running on Win9x or pre Windows XP uncomment the following
//#include <wspiapi.h>

#include <stdio.h>
#include <stdlib.h>

//
// Function: usage
//
// Description:
//    Prints usage information for application
//
void usage(char *progname)
{
    fprintf(stderr, "usage: %s [-n name] [-s port/service] [-a 4|6] [-t s|u] [-p tcp|udp] [-b]\n", progname);
    fprintf(stderr, "   -n name            Host name to resolve\n");
    fprintf(stderr, "   -s port/service    Service name or port number to resolve\n");
    fprintf(stderr, "   -a address-family  Preferred address family\n"
                    "      4                   IPv4 (AF_INET)\n"
                    "      6                   IPv6 (AF_INET6)\n");
    fprintf(stderr, "   -t socket-type     Preferred socket type\n"
                    "      stream              Stream socket (SOCK_STREAM)\n"
                    "      dgram               Datagram socket (SOCK_DGRAM)\n");
    fprintf(stderr, "   -p protocol        Preferred protocol\n"
                    "      tcp                 TCP (IPPROTO_TCP)\n"
                    "      udp                 UDP (IPPROTO_UDP)\n");
    fprintf(stderr, "   -f flag            Flags passed to getname info (may appear multiple times)\n"
                    "      nofqdn               NI_NOFQDN\n"
                    "      numerichost          NI_NUMERICHOST\n"
                    "      namereqd             NI_NAMEREQD\n"
                    "      numericserv          NI_NUMERICSERV\n"
                    "      dgram                NI_DGRAM\n");
    fprintf(stderr, "   -b                 Obtain the bind address for the given address family\n");
           
    ExitProcess(-1);
}

//
// Function: PrintParameters
//
// Description:
//    Prints the parameters passed into the application before attempting to
//    resolve the requested name and service.
//
void PrintParameters(char *host, char *serv, int af, int type, int proto, int flags)
{
    printf("\n");
    printf("Attempting to resolve the host: %s\n", (host ? host: "NULL"));
    printf("Service/port information is   : %s\n", (serv ? serv: "NULL"));
    if (af == AF_INET)
        printf("Requested address family      : AF_INET\n");
    else if (af == AF_INET6)
        printf("Requested address family      : AF_INET6\n");
    else
        printf("Requested address family      : NONE (default is AF_UNSPEC)\n");
    if (type == SOCK_STREAM)
        printf("Requested socket type         : SOCK_STREAM\n");
    else if (type == SOCK_DGRAM)
        printf("Requested socket type         : SOCK_DGRAM\n");
    else
        printf("Requested socket type         : NONE\n");
    if (proto == IPPROTO_TCP)
        printf("Requested protocol            : IPPROTO_TCP\n");
    else if (proto == IPPROTO_UDP)
        printf("Requested protocol            : IPPROTO_UDP\n");
    else
        printf("Requested protocol            : NONE\n");
    printf("Requested flags to getnameinfo: ");
    if (flags & NI_NOFQDN)
        printf("NI_NOFQDN ");
    if (flags & NI_NUMERICHOST)
        printf("NI_NUMERICHOST ");
    if (flags & NI_NAMEREQD)
        printf("NI_NAMEREQD ");
    if (flags & NI_NUMERICSERV)
        printf("NI_NUMERICSERV ");
    if (flags & NI_DGRAM)
        printf("NI_DGRAM ");
    printf("\n\n");
}

//
// Function: main
//
// Description:
//    This routine takes the host and service information obtained from
//    the command line and calls getaddrinfo. The first getaddrinfo call
//    assumes that a numeric string address was passed. If that call fails
//    then it will attempt to resolve the name via DNS. After getaddrinfo
//    succeeds, then for each address returned we will call getnameinfo
//    to resolve it back to its hostname along with displaying the numeric
//    string address.
//
int __cdecl main(int argc, char **argv)
{
    WSADATA          wsd;
    struct addrinfo  hints,
                    *res=NULL,
                    *ptr;
    int              rc,
                     count,
                     i;

    // Variables for getnameinfo
    char             host[NI_MAXHOST],
                     serv[NI_MAXSERV],
                     numerichost[NI_MAXHOST];
    int              hostlen=NI_MAXHOST,
                     servlen=NI_MAXSERV,
                     numerichostlen=NI_MAXHOST,
                     flags=0;

    // Variables for getaddrinfo
    int              AddressFamily=AF_UNSPEC,
                     SocketType=0,
                     Protocol=0;
    char            *HostName=NULL,
                    *ServPort=NULL;
    BOOL             bGetBindAddress=FALSE;

    // Load Winsock
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        fprintf(stderr, "Unable to load Winsock: %d\n", GetLastError());
        return -1;
    }
    //
    // Parse the command line arguments
    //
    for(i=1; i < argc ;i++)
    {
        if ((argv[i][0] != '-') && (argv[i][0] != '/') && (strlen(argv[i]) < 2))
            usage(argv[0]);
        switch (tolower(argv[i][1]))
        {
            case 'a':       // address family
                if (i+1 >= argc)
                    usage(argv[0]);
                if (atoi(argv[i+1]) == 4)
                    AddressFamily = AF_INET;
                else if (atoi(argv[i+1]) == 6)
                    AddressFamily = AF_INET6;
                else
                    usage(argv[0]);
                i++;
                break;
            case 'b':       // get the bind address only
                bGetBindAddress = TRUE;
                break;
            case 'f':       // flags for getnameinfo
                if (i+1 >= argc)
                    usage(argv[0]);
                if (_strnicmp(argv[i+1], "nofqdn", 6) == 0)
                    flags |= NI_NOFQDN;
                else if (_strnicmp(argv[i+1], "numerichost", 11) == 0)
                    flags |= NI_NUMERICHOST;
                else if (_strnicmp(argv[i+1], "namereqd", 8) == 0)
                    flags |= NI_NAMEREQD;
                else if (_strnicmp(argv[i+1], "numericserv", 11) == 0)
                    flags |= NI_NUMERICSERV;
                else if (_strnicmp(argv[i+1], "dgram", 5) == 0)
                    flags |= NI_DGRAM;
                else
                    usage(argv[0]);
                i++;
                break;
            case 'n':       // name to resolve
                if (i+1 >= argc)
                    usage(argv[0]);
                HostName = argv[++i];
                break;
            case 'p':       // protocol to resove for
                if (i+1 >= argc)
                    usage(argv[0]);
                if (_strnicmp(argv[i+1], "tcp", 3) == 0)
                    Protocol = IPPROTO_TCP;
                else if (_strnicmp(argv[i+1], "udp", 3) == 0)
                    Protocol = IPPROTO_UDP;
                else
                    usage(argv[0]);
                i++;
                break;
            case 's':       // port/service to resolve
                if (i+1 >= argc)
                    usage(argv[0]);
                ServPort = argv[++i];
                break;
            case 't':       // socket type
                if (i+1 >= argc)
                    usage(argv[0]);
                if (_strnicmp(argv[i+1], "stream", 6) == 0)
                    SocketType = SOCK_STREAM;
                else if (_strnicmp(argv[i+1], "dgram", 5) == 0)
                    SocketType = SOCK_DGRAM;
                else
                    usage(argv[0]);
                i++;
                break;
            default:
                usage(argv[0]);
                break;
        }
    }
    //
    // Check for the minumum parameters required
    //
    if (!HostName && !ServPort)
    {
        fprintf(stderr, "\n\nYou must specify at least a host name or service name\n\n");
        usage(argv[0]);
    }

    if ((flags & NI_NUMERICSERV) == 0)
    {
        printf("\nNOTE: Without the NI_NUMERICSERV flag (-f numericserv) getnameinfo will\n"
               "      fail if the port information does not resolve to a well known service\n"
               "      like ftp (21), etc.\n\n");
    }

    PrintParameters(HostName, ServPort, AddressFamily, SocketType, Protocol, flags);

    //
    // Resolve the name/address - first assume that the name might be a string
    // literal address
    //
    memset(&hints, 0, sizeof(hints));
    if (bGetBindAddress == TRUE)
        hints.ai_flags = AI_PASSIVE;
    else
        hints.ai_flags = AI_NUMERICHOST;
    hints.ai_family    = AddressFamily;
    hints.ai_socktype  = SocketType;
    hints.ai_protocol  = Protocol;

    rc = getaddrinfo(
            HostName,
            ServPort,
           &hints,
           &res
            );
    if (rc != 0)
    {
        if (rc == WSAHOST_NOT_FOUND)
        {
            //
            // Host name to resolve isn't a string literal, now try a DNS lookup
            // The numerichost lookup is done first since it doesn't actually 
            //  send a request on the network and will fail quickly if it isn't a
            //  numeric address.
            //
            hints.ai_flags = AI_CANONNAME;
            rc = getaddrinfo(
                    HostName,
                    ServPort,
                   &hints,
                   &res
                    );
            if (rc != 0)
            {
                fprintf(stderr, "getaddrinfo failed: %d\n", rc);
                return -1;
            }
        }
        else
        {
            fprintf(stderr, "getaddrinfo failed: %d\n", rc);
            return -1;
        }
    }

    //
    // Count how many addresses were returned
    //
    count = 0;
    ptr   = res;
    while (ptr)
    {
        count++;
        ptr = ptr->ai_next;
    }

    printf("Hostname '%s' resolved to %d addresses\n\n", HostName, count);

    //
    //Do a reverse lookup on each of the resolved address
    //
    count = 1;
    ptr   = res;
    while (ptr)
    {
        host[0] = '\0';
        serv[0] = '\0';

        //
        // First convert the binary addresses returned from getaddrinfo into
        // their numeric string form so we can see the address returned.
        //
        rc = getnameinfo(
                ptr->ai_addr,
                ptr->ai_addrlen,
                numerichost,
                numerichostlen,
                NULL,
                0,
                NI_NUMERICHOST
                );
        if (rc != 0)
        {
            fprintf(stderr, "getnameinfo failed: %d\n", rc);
            return -1;
        }

        printf("[%d] Numeric address resolved: %s\n", count, numerichost);
        
        //
        // Now attemp to reverse lookup according the parameters passed in
        // by the user
        //
        rc = getnameinfo(
                ptr->ai_addr,
                ptr->ai_addrlen,
                host,
                hostlen,
                serv,
                servlen,
                flags
                );
        if (rc != 0)
        {
            fprintf(stderr, "getnameinfo failed: %d for the address: %s\n", rc, numerichost);
        }
        else
        {
            printf("[%d] Host:    %s\n", count, host);
            printf("[%d] Service: %s\n", count, serv);
        }

        printf("\n");

        count++;

        // Goto the next address
        ptr = ptr->ai_next;
    }

    // Free up the results from getaddrinfo
    freeaddrinfo(res);

    WSACleanup();
    
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -