6

前回の質問で回答が得られなかったので、言い直します。

PC 名 (NetBIOS 名) を使用して gethostbyname() を実行するときに、IP アドレスの順序 (IP アドレスが 1 つのインターフェースにバインドされている場合) が使用されますか?

私はこのコードを持っています:

#include <iostream>
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    char hostname[255];
    struct hostent *he;
    struct in_addr **addr_list;

    WSAData data;
    WSAStartup(MAKEWORD(2, 2), &data);

    gethostname(hostname, 255);
    std::cout << "Host name: " << hostname << std::endl;

    if ((he = gethostbyname(hostname)) == NULL) {
        std::cout << "gethostbyname error" << std::endl;
    } else {
        std::cout << "IP addresses: "  << std::endl;
        addr_list = (struct in_addr **)he->h_addr_list;
        for(int i = 0; addr_list[i] != NULL; i++) {
            std::cout << inet_ntoa(*addr_list[i]) << std::endl;
        }
    }
    std::cin.get();
}

また、Windows Server 2012 と Windows Server 2008 / Windows 7 では異なる結果が得られます。Windows 7 を搭載した自宅の PC では、昇順が使用されます。

Host name: SplattWin
IP addresses:
192.168.1.140
192.168.3.1
192.168.3.2
192.168.3.3
192.168.3.4

ただし、Windows サーバー 2012 では、降順で IP アドレスが表示されます。

Host name: WinServ
IP addresses:
1.1.1.4
1.1.1.3
1.1.1.2
1.1.1.1

再注文する方法はありますか?これらの IP アドレスを追加するときに skipassource フラグを試しましたが、この場合はうまくいかないようです。

gethostname() に続いて gethostbyname() を使用して独自の IP アドレスを決定するサードパーティ ソフトウェアがあります (リストの最初に取得されます)。また、システムに新しい IP アドレスを追加するたびに、設定とクライアント側を変更する必要があるのは本当にイライラします。

4

1 に答える 1

2

IP の順序は、インターフェイスの優先順位などに基づいて Windows によって決定されます。マシンの境界や Windows のバージョンの境界にまたがる標準ルールはありません。出力リストをランダムとして扱い、特定のニーズに合わせて IP を自分で並べ替える必要があります。例えば:

#include <iostream>
#include <vector>
#include <algorithm>
#include <winsock.h>

#pragma comment(lib, "Ws2_32.lib")

bool SortInAddr(const in_addr &a, const in_addr &b)
{
    return (a.S_un.S_addr < b.S_un.S_addr);
} 

int main()
{
    WSAData data;
    WSAStartup(MAKEWORD(2, 2), &data);

    char hostname[256] = {0};
    if (gethostname(hostname, 255) == SOCKET_ERROR)
    {
        std::cout << "gethostname error: " << WSAGetLastError() << std::endl;
    }
    else
    {
        std::cout << "Host name: " << hostname << std::endl;

        struct hostent *he = gethostbyname(hostname);
        if (he == NULL)
        {
            std::cout << "gethostbyname error: " << WSAGetLastError() << std::endl;
        }
        else if (he->h_length != sizeof(in_addr))
        {
            std::cout << "gethostbyname did not return IPv4 addresses" << std::endl;
        }
        else
        {
            std::vector<in_addr> addrs;

            struct in_addr **addr_list = (struct in_addr **)(he->h_addr_list);
            for(int i = 0; addr_list[i] != NULL; ++i)
            {
                addrs.push_back(*(addr_list[i]));
            }

            if (addrs.size() > 1)
            {
                std::sort(addrs.begin(), addrs.end(), SortInAddr);
            }

            std::cout << "IPv4 addresses: " << std::endl;
            for(std::vector<in_addr>::iterator iter = addrs.begin();
                iter != addrs.end();
                ++iter)
            {
                std::cout << inet_ntoa(addrs[i]) << std::endl;
            }
        }
    }

    WSACleanup();
    std::cin.get();
}

そうは言っても、マシンのローカル インターフェイスを列挙するためにgethostbyname()(または) を使用しないでください。getaddrinfo()そのような機能は、その目的を意図したものではありません。代わりにGetAdaptersInfo()またはを使用してください。GetAdaptersAddresses()これらは特にローカル インターフェイスを列挙することを目的としており、インターフェイスに関するより詳細な情報を提供します。

于 2014-11-12T18:10:55.683 に答える