如何获得路由器网关?

时间:2014-10-01 21:14:21

标签: delphi ip router

我正在使用例程来收集内部IP地址,当只有一个IP地址时,它可以很好地工作。但是,在我的笔记本电脑上,它安装了VMWare Player,它有两个虚拟适配器,这些IP出现在列表中。

192.168.41.7 - 192.168.5.4 - 192.168.1.10

前两个是VMWare的虚拟适配器。我知道路由器网关是192.168.1.1。所以,如果我能以编程方式读取路由器网关,那么我可以匹配IP的第三段,以了解我所追踪的那个。

我找到了一些指向MS网站的链接以获取适配器信息,但我正在寻找一些代码片段,因为我不知道从哪里开始获取MS详细信息。

有人可以在某些网站协助或指点我。

1 个答案:

答案 0 :(得分:2)

GetAdaptersInfo()GetAdaptersAddresses()都会为每个网络适配器报告本地IP和网关。例如:

uses
  ..., IpTypes, IpHlpApi;

  procedure GetLocalAddressesByAdaptersAddresses;
  var
    Ret: DWORD;
    BufLen: ULONG;
    Adapter, Adapters: PIP_ADAPTER_ADDRESSES;
    UnicastAddr: PIP_ADAPTER_UNICAST_ADDRESS;
    Gateway: PIP_ADAPTER_GATEWAY_ADDRESS;
    IPAddr: string;
  begin
    // MSDN says:
    // The recommended method of calling the GetAdaptersAddresses function is
    // to pre-allocate a 15KB working buffer pointed to by the AdapterAddresses
    // parameter. On typical computers, this dramatically reduces the chances
    // that the GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW,
    // which would require calling GetAdaptersAddresses function multiple times.

    BufLen := 1024*15;
    GetMem(Adapters, BufLen);
    try
      repeat
        // TODO: include GAA_FLAG_INCLUDE_ALL_INTERFACES on Vista+?
        Ret := GetAdaptersAddresses(PF_UNSPEC, GAA_FLAG_SKIP_ANYCAST or GAA_FLAG_SKIP_MULTICAST or GAA_FLAG_SKIP_DNS_SERVER or GAA_FLAG_SKIP_FRIENDLY_NAME or GAA_FLAG_INCLUDE_GATEWAYS, nil, Adapters, BufLen);
        case Ret of
          ERROR_SUCCESS:
          begin
            // Windows CE versions earlier than 4.1 may return ERROR_SUCCESS and
            // BufLen=0 if no adapter info is available, instead of returning
            // ERROR_NO_DATA as documented...
            if BufLen = 0 then begin
              Exit;
            end;
            Break;
          end;
          ERROR_NOT_SUPPORTED:
          begin
            Result := False;
            Exit;
          end;
          ERROR_NO_DATA,
          ERROR_ADDRESS_NOT_ASSOCIATED:
            Exit;
          ERROR_BUFFER_OVERFLOW:
            ReallocMem(Adapters, BufLen);
        else
          RaiseLastError(Ret);
        end;
      until False;

      if Ret = ERROR_SUCCESS then
      begin
        Adapter := Adapters;
        repeat
          if (Adapter.IfType <> IF_TYPE_SOFTWARE_LOOPBACK) and
            ((Adapter.Flags and IP_ADAPTER_RECEIVE_ONLY) = 0) then
          begin
            UnicastAddr := Adapter^.FirstUnicastAddress;
            while UnicastAddr <> nil do
            begin
              if UnicastAddr^.DadState = IpDadStatePreferred then
              begin
                case UnicastAddr^.Address.lpSockaddr.sin_family of
                  AF_INET: begin
                    // use PSockAddrIn(UnicastAddr^.Address.lpSockaddr)^.sin_addr as needed...
                  end;
                  AF_INET6: begin
                    // use PSockAddrIn6(UnicastAddr^.Address.lpSockaddr)^.sin6_addr as needed...
                  end;
                end;
              end;
              UnicastAddr := UnicastAddr^.Next;
            end;
            Gateway := Adapter^.FirstGatewayAddress;
            while Gateway <> nil do
            begin
              case Gateway^.Address.lpSockaddr.sin_family of
                AF_INET: begin
                  // use PSockAddrIn(Gateway^.Address.lpSockaddr)^.sin_addr as needed...
                end;
                AF_INET6: begin
                  // use PSockAddrIn6(Gateway^.Address.lpSockaddr)^.sin6_addr as needed...
                end;
              end;
              Gateway := Gateway^.Next;
            end;
          end;
          Adapter := Adapter^.Next;
        until Adapter = nil;
      end;
    finally
      FreeMem(Adapters);
    end;
  end;

  procedure GetLocalAddressesByAdaptersInfo;
  var
    Ret: DWORD;
    BufLen: ULONG;
    Adapter, Adapters: PIP_ADAPTER_INFO;
    IPAddr, Gateway: PIP_ADDR_STRING;
  begin
    BufLen := 1024*15;
    GetMem(Adapters, BufLen);
    try
      repeat
        Ret := GetAdaptersInfo(Adapters, BufLen);
        case Ret of
          ERROR_SUCCESS:
          begin
            // Windows CE versions earlier than 4.1 may return ERROR_SUCCESS and
            // BufLen=0 if no adapter info is available, instead of returning
            // ERROR_NO_DATA as documented...
            if BufLen = 0 then begin
              Exit;
            end;
            Break;
          end;
          ERROR_NOT_SUPPORTED,
          ERROR_NO_DATA:
            Exit;
          ERROR_BUFFER_OVERFLOW:
            ReallocMem(Adapters, BufLen);
        else
          RaiseLastOSError(Ret);
        end;
      until False;

      if Ret = ERROR_SUCCESS then
      begin
        Adapter := Adapters;
        repeat
          IPAddr := @(Adapter^.IpAddressList);
          repeat
            // use IPAddr^.IpAddress.S as needed...
            IPAddr := IPAddr^.Next;
          until IPAddr = nil;
          Gateway := @(Adapter^.GatewayList);
          repeat
            // use Gateway^.IpAddress.S as needed...
            Gateway := Gateway^.Next;
          until Gateway = nil;
          Adapter := Adapter^.Next;
        until Adapter = nil;
      end;
    finally
      FreeMem(Adapters);
    end;
  end;