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

📄 addrquery.cpp

📁 < WINDOWS网络编程>>英文版,一本详细讲解WINDOWS平台下网络编程的国外经典书籍,适合英文水平高的牛人
💻 CPP
字号:
//
// Sample: SIO_ADDRESS_LIST_QUERY and SIO_ADDRESS_LIST_CHANGE ioctls
//
// Files:
//      addrquery.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 all local
//      IPv4 and IPv6 interfaces as well as register for notification when
//      the local addresses change. This sample enumerates the local interfaces
//      and then registers for a change notfication. To trigger the notification
//      you can either disable the adapter from the network controll panel or
//      unplug the network cable. After the event occurs, the sample retrieves
//      the current interface list and registers for the event again, etc.
//
// Compile:
//      cl -o addrquery.exe addrquery.cpp resolve.cpp ws2_32.lib
//
// Usage:
//      addrquery.exe [options]
//          -a 4|6 Specifies the address family (default = AF_UNSPEC)
//             4       AF_INET
//             6       AF_INET6
//          -s     Sort addresses (supported on v6 only)
//
#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
int gSortAddresses=FALSE;               // Sort addresses first?

// 
// Function: usage
// 
// Description:
//    Print usage information and exit.
//
void usage(char *progname)
{
    fprintf(stderr, "usage: %s [-a 4|6] [-s]\n"
                    "       -a 4|6      Specifies the address family (default = AF_UNSPEC)\n"
                    "           4       AF_INET\n"
                    "           6       AF_INET6\n"
                    "       -s          Sort addresses\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];
    struct addrinfo *local=NULL,
                    *ptr=NULL;
    SOCKET_ADDRESS_LIST *slist=NULL;
    DWORD            bytes;
    char             addrbuf[ADDRESS_LIST_BUFFER_SIZE];
    int              socketcount=0,
                     addrbuflen=ADDRESS_LIST_BUFFER_SIZE,
                     rc,
                     i, j;


    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 's':
                gSortAddresses = TRUE;
                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
    local = ResolveAddress(NULL, "0", gAddressFamily, SOCK_DGRAM, IPPROTO_UDP);
    if (local == NULL)
    {
        fprintf(stderr, "Unable to resolve the bind address!\n");
        return -1;
    }

    // Create a socket and event for each address returned
    ptr = local;
    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)
    {
        for(i=0; i < socketcount ;i++)
        {
            memset(&ol[i], 0, sizeof(WSAOVERLAPPED));

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

            rc = WSAIoctl(
                    s[i],
                    SIO_ADDRESS_LIST_QUERY,
                    NULL,
                    0,
                    addrbuf,
                    addrbuflen,
                   &bytes,
                    NULL,
                    NULL
                    );
            if (rc == SOCKET_ERROR)
            {
                fprintf(stderr, "WSAIoctl: SIO_ADDRESS_LIST_QUERY failed: %d\n", WSAGetLastError());
                return -1;
            }

            // If requestd, sort the addresses. Note that the sort ioctl only works
            //    with IPv6 addresses (as it doesn't make sense for IPv4)
            if (gSortAddresses)
            {
                rc = WSAIoctl(
                        s[i],
                        SIO_ADDRESS_LIST_SORT,
                        addrbuf,
                        bytes,
                        addrbuf,
                        addrbuflen,
                       &bytes,
                        NULL,
                        NULL
                        );
                if (rc == SOCKET_ERROR)
                {
                    fprintf(stderr, "WSAIoctl: SIO_ADDRESS_LIST_SORT failed: %d\n", WSAGetLastError());
                }
            }

            // Print out the addresses
            slist = (SOCKET_ADDRESS_LIST *)addrbuf;
            for(j=0; j < slist->iAddressCount ;j++)
            {
                printf("Address [%d]: ", j);
                PrintAddress(slist->Address[j].lpSockaddr, slist->Address[j].iSockaddrLength);
                printf("\n");
            }
            printf("\n");

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

        // Actually, when you unplug/plug in the cable the socket will receive
        //    more than one notification -- one for the cable removal/insertion
        //    and one or more for DHCP nofication
        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("Address list change signaled!\n");

        WSAResetEvent(hEvent[rc - WAIT_OBJECT_0]);

        // Event was signaled, go back and enumerate the addresses...
    }

    freeaddrinfo(local);

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

    WSACleanup();

    return 0;
}

⌨️ 快捷键说明

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