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

📄 routequery.cpp

📁 < WINDOWS网络编程>>英文版,一本详细讲解WINDOWS平台下网络编程的国外经典书籍,适合英文水平高的牛人
💻 CPP
字号:
//
// Sample: SIO_INTERFACE_LIST_QUERY and SIO_INTERFACE_LIST_CHANGE ioctls
//
// Files:
//      routequery.cpp      - this file
//      resolve.cpp         - common routines for resolving addresses, etc.
//      resolve.h           - header file for resolve.cpp
//
// Description:
//      This sample illustrates how an application can query for the local
//      route which is used to reach a given destination address. After
//      the route is resolved, it registers for any changes on that route.
//      To trigger nofication you can either disable the corresponding
//      interface in the network connection folder or by unplugging the 
//      network cable. After the event is triggered, the route is queried
//      again.
//
// Compile:
//      cl -o routequery.exe routequery.cpp resolve.cpp ws2_32.lib
//
// Usage:
//      routequery.exe [options]
//          -a 4|6      Specifies the address family (default = AF_UNSPEC)
//              4       AF_INET
//              6       AF_INET6
//          -n dest     Destination address/host to find a route to
//
#include <winsock2.h>
#include <ws2tcpip.h>

#include "resolve.h"

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

#define ADDRESS_LIST_BUFFER_SIZE        4096

int   gAddressFamily=AF_UNSPEC;           // Address family to use
char *gRouteToAddress=NULL;               // Address to find the local interface
                                          // that it is reachable from
// 
// Function: usage
// 
// Description:
//    Print usage information and exit.
//
void usage(char *progname)
{
    fprintf(stderr, "usage: %s [-a 4|6] [-n destination]\n"
                    "       -a 4|6      Specifies the address family (default = AF_UNSPEC)\n"
                    "           4       AF_INET\n"
                    "           6       AF_INET6\n"
                    "       -n dest     Destination address/host to find a route to\n",
                    progname
                    );
    ExitProcess(-1);
}

//
// Function: main
//
// Description:
//    Parse the command line, enumeate the local addresses (IPv4/6), enumerate the
//    interfaces, and listen for address change notifications. This is performed
//    in an infinite loop.
//
int __cdecl main(int argc, char **argv)
{
    WSADATA          wsd;
    SOCKET           s[MAXIMUM_WAIT_OBJECTS];
    WSAEVENT         hEvent[MAXIMUM_WAIT_OBJECTS];
    WSAOVERLAPPED    ol[MAXIMUM_WAIT_OBJECTS];
    SOCKADDR_STORAGE LocalIf;
    struct addrinfo *routeto=NULL,
                    *ptr=NULL;
    DWORD            bytes;
    int              socketcount=0,
                     rc,
                     i;

    // Parse the command line
    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':
                if (i+1 >= argc)
                    usage(argv[0]);
                if (argv[i+1][0] == '4')
                    gAddressFamily = AF_INET;
                else if (argv[i+1][0] == '6')
                    gAddressFamily = AF_INET6;
                else
                    usage(argv[0]);
                i++;
                break;
            case 'n':
                gRouteToAddress = argv[++i];
                break;
            default:
                usage(argv[0]);
                break;
        }
    }

    // Load Winsock
    rc = WSAStartup(MAKEWORD(2,2), &wsd);
    if (rc != 0)
    {
        fprintf(stderr, "Unable to load Winsock: %d\n", rc);
        return -1;
    }

    // Enumerate the local bind addresses - to wait for changes we only need
    //    one socket but to enumerate the addresses for a particular address
    //    family, we need a socket of that type
    routeto = ResolveAddress(gRouteToAddress, "0", gAddressFamily, SOCK_DGRAM, IPPROTO_UDP);
    if (routeto == NULL)
    {
        fprintf(stderr, "Unable to resolve the bind address!\n");
        return -1;
    }

    // Create a socket and event for each address returned
    ptr = routeto;
    while (ptr)
    {
        s[socketcount] = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (s[socketcount] == INVALID_SOCKET)
        {
            fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
            return -1;
        }

        hEvent[socketcount] = WSACreateEvent();
        if (hEvent == NULL)
        {
            fprintf(stderr, "WSACreateEvent failed: %d\n", WSAGetLastError());
            return -1;
        }

        socketcount++;

        ptr = ptr->ai_next;

        if (ptr && (socketcount > MAXIMUM_WAIT_OBJECTS))
        {
            printf("Too many address families returned!\n");
            break;
        }
    }

    // Go into a loop - first enumerate the addresses then wait for a change
    while (1)
    {
        i=0;
        ptr = routeto;
        while (ptr)
        {
            memset(&ol[i], 0, sizeof(WSAOVERLAPPED));

            ol[i].hEvent = hEvent[i];

            rc = WSAIoctl(
                    s[i],
                    SIO_ROUTING_INTERFACE_QUERY,
                    ptr->ai_addr,
                    ptr->ai_addrlen,
                    (SOCKADDR *)&LocalIf,
                    sizeof(LocalIf),
                   &bytes,
                    NULL,
                    NULL
                    );
            if (rc == SOCKET_ERROR)
            {
                if (WSAGetLastError() == WSAEHOSTUNREACH)
                {
                    printf("No route to host: %s\n", gRouteToAddress);
                }
                else
                {
                    fprintf(stderr, "WSAIoctl: SIO_ROUTING_INTERFACE_QUERY failed: %d\n", WSAGetLastError());
                    return -1;
                }
            }
            else
            {
                // Print out the addresses
                printf("Local interface: ");
                PrintAddress((SOCKADDR *)&LocalIf, bytes);
                printf(" to reach: %s\n", gRouteToAddress);
            }

            // Register for change notification
            rc = WSAIoctl(
                    s[i],
                    SIO_ROUTING_INTERFACE_CHANGE,
                    ptr->ai_addr,
                    ptr->ai_addrlen,
                    NULL,
                    0,
                   &bytes,
                   &ol[i],
                    NULL
                    );
            if (rc == SOCKET_ERROR)
            {
                if (WSAGetLastError() != WSA_IO_PENDING)
                {
                    fprintf(stderr, "WSAIoctl: SIO_ROUTING_INTERFACE_CHANGE failed: %d\n", WSAGetLastError());
                    return -1;
                }
            }

            // Increment our counter/pointer
            i++;
            ptr = ptr->ai_next;

            // If a ton of address families were returned, make sure we don't exceed
            //    our limit.
            if (ptr && (socketcount > MAXIMUM_WAIT_OBJECTS))
            {
                break;
            }
        }
        printf("\n");

        printf("Unplug network cable or disable adapter...\n");

        rc = WaitForMultipleObjectsEx(socketcount, hEvent, FALSE, INFINITE, TRUE);
        if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
        {
            fprintf(stderr, "WaitForMultipleObjectsEx failed: %d\n", GetLastError());
            return -1;
        }

        printf("Routing interface change signaled!\n");

        WSAResetEvent(hEvent[rc - WAIT_OBJECT_0]);

        // Event was signaled, go back and find the route to the destination...
    }

    freeaddrinfo(routeto);

    for(i=0; i < socketcount ;i++)
    {
        closesocket(s[i]);
    }

    WSACleanup();

    return 0;
}

⌨️ 快捷键说明

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