WindowsAPI|每天了解几个winAPI接口之网络配置相关文档Iphlpapi.h详细分析9

上一篇:WindowsAPI|每天了解几个winAPI接口之网络配置相关文档Iphlpapi.h详细分析八

如果有错误欢迎指正批评,在此只作为科普和参考。

C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\iphlpapi.h

文章目录

  • [GetBestInterfaceEx:同时支持 IPv4 和 IPv6,用来查询"到指定目的地址时,本机应该把包从哪块网卡发出去"](#GetBestInterfaceEx:同时支持 IPv4 和 IPv6,用来查询“到指定目的地址时,本机应该把包从哪块网卡发出去”)
      • [1. 与 `GetBestInterface` 区别](#1. 与 GetBestInterface 区别)
      • [2. 函数原型](#2. 函数原型)
      • [3. 最小示例(IPv4)](#3. 最小示例(IPv4))
      • [4. 最小示例(IPv6)](#4. 最小示例(IPv6))
      • [5. 常见错误码](#5. 常见错误码)
      • [6. 使用场景](#6. 使用场景)
  • [GetBestRoute:给定一个 IPv4 目标地址(以及可选的源地址),把系统路由表里『最长前缀匹配 + 最低 Metric』的那条路由整行取出来](#GetBestRoute:给定一个 IPv4 目标地址(以及可选的源地址),把系统路由表里『最长前缀匹配 + 最低 Metric』的那条路由整行取出来)
      • [1. 函数原型](#1. 函数原型)
      • [2. 与 GetBestInterface/Ex 的区别](#2. 与 GetBestInterface/Ex 的区别)
      • [3. MIB_IPFORWARDROW 关键字段](#3. MIB_IPFORWARDROW 关键字段)
      • [4. 行为细节](#4. 行为细节)
      • [5. 最小示例](#5. 最小示例)
      • [6. 使用场景](#6. 使用场景)
  • [NotifyAddrChange:给我一个异步事件,只要本机任何 IPv4/IPv6 地址(或接口状态)发生增删改,立刻通知我](#NotifyAddrChange:给我一个异步事件,只要本机任何 IPv4/IPv6 地址(或接口状态)发生增删改,立刻通知我)
      • [1. 函数原型](#1. 函数原型)
      • [2. 两种使用模式](#2. 两种使用模式)
      • [3. 事件触发场景](#3. 事件触发场景)
      • [4. 最小示例(同步阻塞)](#4. 最小示例(同步阻塞))
      • [5. 最小示例(异步 IOCP)](#5. 最小示例(异步 IOCP))
      • [6. 清理](#6. 清理)
      • [7. 与相关 API 区别](#7. 与相关 API 区别)
  • [NotifyRouteChange:给我一个异步事件,只要本机 IPv4 路由表发生任何增、删、改,就立刻通知我](#NotifyRouteChange:给我一个异步事件,只要本机 IPv4 路由表发生任何增、删、改,就立刻通知我)
      • [1. 函数原型](#1. 函数原型)
      • [2. 触发场景](#2. 触发场景)
      • [3. 使用模式](#3. 使用模式)
      • [4. 最小示例(同步阻塞)](#4. 最小示例(同步阻塞))
      • [5. 取消与清理](#5. 取消与清理)
      • [6. 与相关 API 对照](#6. 与相关 API 对照)
  • [CancelIPChangeNotify:"取消"之前通过 异步方式 注册的 IP 地址或路由变化通知](#CancelIPChangeNotify:“取消”之前通过 异步方式 注册的 IP 地址或路由变化通知)
      • [1. 函数原型](#1. 函数原型)
      • [2. 使用场景](#2. 使用场景)
      • [3. 典型调用流程](#3. 典型调用流程)
      • [4. 注意事项](#4. 注意事项)
  • [GetAdapterIndex:把网卡的『友好名称』(Unicode 字符串) 转换成对应的接口索引 (ifIndex)](#GetAdapterIndex:把网卡的『友好名称』(Unicode 字符串) 转换成对应的接口索引 (ifIndex))
      • [1. 函数原型](#1. 函数原型)
      • [2. 友好名称是什么?](#2. 友好名称是什么?)
      • [3. 最小示例](#3. 最小示例)
      • [4. 常见用途](#4. 常见用途)
      • [5. 注意点](#5. 注意点)
  • [AddIPAddress:把指定的 IPv4 地址/掩码临时添加到某块网卡上,立刻生效,重启后失效](#AddIPAddress:把指定的 IPv4 地址/掩码临时添加到某块网卡上,立刻生效,重启后失效)
      • [1. 函数原型](#1. 函数原型)
      • [2. 关键概念:NTEContext / NTEInstance](#2. 关键概念:NTEContext / NTEInstance)
      • [3. 生命周期](#3. 生命周期)
      • [4. 最小示例](#4. 最小示例)
      • [5. 删除临时地址](#5. 删除临时地址)
      • [6. 常见错误码](#6. 常见错误码)
      • [7. 典型用途](#7. 典型用途)
  • [DeleteIPAddress:把之前用 AddIPAddress 临时添加的 IPv4 地址立即删除](#DeleteIPAddress:把之前用 AddIPAddress 临时添加的 IPv4 地址立即删除)

GetBestInterfaceEx:同时支持 IPv4 和 IPv6,用来查询"到指定目的地址时,本机应该把包从哪块网卡发出去"

cpp 复制代码
#pragma region Application Family or OneCore Family or Games Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)

#pragma warning(push)
#pragma warning(disable:4115)
IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
GetBestInterfaceEx(
    _In_  struct sockaddr *pDestAddr,
    _Out_ PDWORD           pdwBestIfIndex
    );
#pragma warning(pop)

#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */
#pragma endregion

GetBestInterfaceExGetBestInterface 的"升级版"------同时支持 IPv4 和 IPv6,用来查询"到指定目的地址时,本机应该把包从哪块网卡发出去"。


1. 与 GetBestInterface 区别

特性 GetBestInterface GetBestInterfaceEx
地址族 仅 IPv4 (IPAddr) IPv4 / IPv6 通用 (sockaddr)
结构体 IPAddr sockaddr_in / sockaddr_in6
适用平台 桌面、系统、游戏 额外支持 UWP/商店应用

2. 函数原型

c 复制代码
DWORD WINAPI GetBestInterfaceEx(
    _In_  struct sockaddr *pDestAddr,   // 指向 IPv4 或 IPv6 地址
    _Out_ PDWORD           pdwBestIfIndex
);
  • pDestAddr
    传入 sockaddr_in(IPv4)或 sockaddr_in6(IPv6),需先填充地址族和端口(端口可为 0)。
  • pdwBestIfIndex
    返回最佳接口的 接口索引 (与 GetAdaptersAddresses 中的 IfIndex 对应)。

3. 最小示例(IPv4)

cpp 复制代码
sockaddr_in dest4 = {};
dest4.sin_family = AF_INET;
dest4.sin_port = 0;                       // 不关心端口
inet_pton(AF_INET, "8.8.8.8", &dest4.sin_addr);

DWORD bestIf;
DWORD err = GetBestInterfaceEx((sockaddr*)&dest4, &bestIf);
if (err == NO_ERROR)
    printf("Best IPv4 interface = %lu\n", bestIf);
else
    printf("Error: %lu\n", err);

4. 最小示例(IPv6)

cpp 复制代码
sockaddr_in6 dest6 = {};
dest6.sin6_family = AF_INET6;
inet_pton(AF_INET6, "2001:4860:4860::8888", &dest6.sin6_addr);

DWORD bestIf6;
DWORD err = GetBestInterfaceEx((sockaddr*)&dest6, &bestIf6);
if (err == NO_ERROR)
    printf("Best IPv6 interface = %lu\n", bestIf6);

5. 常见错误码

错误码 含义
NO_ERROR 成功
ERROR_INVALID_PARAMETER 地址族非法或指针为空
ERROR_NOT_FOUND 找不到有效路由(例如路由表为空)

6. 使用场景

  • 网络诊断工具:判断目标走哪条链路。
  • VPN/代理:在添加路由前探测真实出口。
  • UWP 应用 :由于 GetBestInterface 仅限桌面分区,GetBestInterfaceEx 是 UWP 中唯一可用的"最佳接口"查询函数。

一句话总结:
GetBestInterfaceEx 是跨协议(IPv4/IPv6)、跨平台(含 UWP)的"路由查询"函数:给它一个 sockaddr,它告诉你数据包会从哪块网卡出去。

GetBestRoute:给定一个 IPv4 目标地址(以及可选的源地址),把系统路由表里『最长前缀匹配 + 最低 Metric』的那条路由整行取出来

cpp 复制代码
#pragma region Desktop Family or OneCore Family or Games Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)

//////////////////////////////////////////////////////////////////////////////
//                                                                          //
// Gets the best (longest matching prefix) route for the given destination  //
// If the source address is also specified (i.e. is not 0x00000000), and    //
// there are multiple "best" routes to the given destination, the returned  //
// route will be one that goes out over the interface which has an address  //
// that matches the source address                                          //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
GetBestRoute(
    _In_      DWORD               dwDestAddr,
    _In_opt_  DWORD               dwSourceAddr,
    _Out_     PMIB_IPFORWARDROW   pBestRoute
    );

GetBestRoute 功能一句话
"给定一个 IPv4 目标地址(以及可选的源地址),把系统路由表里『最长前缀匹配 + 最低 Metric』的那条路由整行取出来。"


1. 函数原型

c 复制代码
DWORD WINAPI GetBestRoute(
    _In_      DWORD             dwDestAddr,   // 目标 IPv4(网络字节序)
    _In_opt_  DWORD             dwSourceAddr, // 源 IPv4(可为 0)
    _Out_     PMIB_IPFORWARDROW pBestRoute    // 整条路由信息
);

返回值

  • NO_ERROR (0) -- 成功
  • ERROR_INVALID_PARAMETER -- 地址非法或指针空
  • ERROR_NO_DATA -- 找不到匹配路由

2. 与 GetBestInterface/Ex 的区别

API 输出内容 协议族 额外信息
GetBestInterface 仅接口索引 IPv4
GetBestInterfaceEx 仅接口索引 IPv4/6
GetBestRoute 完整 MIB_IPFORWARDROW 路由行 IPv4

3. MIB_IPFORWARDROW 关键字段

c 复制代码
typedef struct _MIB_IPFORWARDROW {
    DWORD dwForwardDest;      // 目的网络
    DWORD dwForwardMask;      // 子网掩码
    DWORD dwForwardPolicy;    // 策略 (通常 0)
    DWORD dwForwardNextHop;   // 下一跳网关
    DWORD dwForwardIfIndex;   // 出口接口
    DWORD dwForwardType;      // 路由类型 (3=direct, 4=remote)
    DWORD dwForwardProto;     // 路由协议
    DWORD dwForwardAge;       // 生存时间
    DWORD dwForwardNextHopAS; // 自治系统号
    DWORD dwForwardMetric1;   // 路由度量
    // ... 还有 Metric2-5
} MIB_IPFORWARDROW, *PMIB_IPFORWARDROW;

4. 行为细节

  • 如果 dwSourceAddr == 0,系统只按 最长前缀 + 最小 Metric 选路。
  • 如果 dwSourceAddr != 0,且出现多条"最优"路由,则优先选择 源地址所在子网 所在接口的那条路由。
  • 目标地址就是主机地址时,返回 主机路由 (掩码 255.255.255.255)。

5. 最小示例

cpp 复制代码
MIB_IPFORWARDROW best;
DWORD ret = GetBestRoute(inet_addr("8.8.8.8"), 0, &best);
if (ret == NO_ERROR) {
    struct in_addr dest, mask, hop;
    dest.S_un.S_addr = best.dwForwardDest;
    mask.S_un.S_addr = best.dwForwardMask;
    hop.S_un.S_addr  = best.dwForwardNextHop;
    printf("Route: Dest=%s Mask=%s NextHop=%s If=%lu Metric=%lu\n",
        inet_ntoa(dest), inet_ntoa(mask), inet_ntoa(hop),
        best.dwForwardIfIndex, best.dwForwardMetric1);
}

6. 使用场景

  • 网络诊断:显示"到某 IP 实际走哪条路由、下一跳是谁"。
  • VPN/多出口:比较不同源地址时的选路差异。
  • 路由可视化工具:替代 route print 的逐行解析。

一句话总结
GetBestRoute 把"路由表里真正会被选中的那一条"完整取出来,让你不仅能知道出口接口,还能直接看到下一跳网关、子网掩码和路由度量。

NotifyAddrChange:给我一个异步事件,只要本机任何 IPv4/IPv6 地址(或接口状态)发生增删改,立刻通知我

cpp 复制代码
IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
NotifyAddrChange(
    _Out_ PHANDLE      Handle,
    _In_  LPOVERLAPPED overlapped
    );

NotifyAddrChange 的作用一句话:
"给我一个异步事件,只要本机任何 IPv4/IPv6 地址(或接口状态)发生增删改,立刻通知我。"


1. 函数原型

c 复制代码
DWORD WINAPI NotifyAddrChange(
    _Out_ PHANDLE      Handle,     // 返回事件句柄(同步模式)或 NULL(异步)
    _In_  LPOVERLAPPED overlapped  // 异步 I/O 用;同步模式可填 NULL
);
  • 返回值
    • NO_ERROR (0) ------ 成功注册
    • ERROR_IO_PENDING ------ 异步已排队(与 OVERLAPPED 配合)
    • 其他 Win32 错误码(权限不足等)

2. 两种使用模式

模式 Handle overlapped 等待方式 典型代码
同步 非 NULL NULL WaitForSingleObject(Handle, INFINITE) 简单阻塞等一次
异步 NULL 有效 OVERLAPPED* GetQueuedCompletionStatus / ReadDirectoryChangesW 风格 服务/驱动长时间监听

3. 事件触发场景

  • 任何接口新增/删除 IPv4 或 IPv6 单播地址
  • DHCP 分配/续租/释放
  • 用户手动改 IP、启用/禁用网卡
  • VPN、拨号连接建立/断开
  • 不报告 路由表、DNS 服务器变化(需 NotifyRouteChange / NotifyUnicastIpAddressChange 等)

4. 最小示例(同步阻塞)

cpp 复制代码
HANDLE hEvent;
DWORD err = NotifyAddrChange(&hEvent, NULL);
if (err == NO_ERROR) {
    printf("Waiting for address change...\n");
    WaitForSingleObject(hEvent, INFINITE);
    printf("Detected address change!\n");
    CloseHandle(hEvent);
}

5. 最小示例(异步 IOCP)

cpp 复制代码
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
OVERLAPPED ovl = {};
DWORD err = NotifyAddrChange(NULL, &ovl);
if (err == ERROR_IO_PENDING) {
    DWORD bytes;
    ULONG_PTR key;
    LPOVERLAPPED pov;
    GetQueuedCompletionStatus(hIOCP, &bytes, &key, &pov, INFINITE);
    // 这里收到通知
}

6. 清理

  • 同步句柄用 CloseHandle
  • 异步调用可用 CancelIoEx 取消挂起的通知。

7. 与相关 API 区别

API 触发条件 协议族
NotifyAddrChange IP 地址变化 IPv4/IPv6
NotifyRouteChange 路由表变化 IPv4
NotifyUnicastIpAddressChange 单播地址变化 IPv4/IPv6(细粒度回调)

一句话总结:
NotifyAddrChange 让你用 事件或异步 I/O 实时监听"本机 IP 地址发生任何变化"这一事件,常用于网络配置守护、VPN 客户端、零配置服务等。

NotifyRouteChange:给我一个异步事件,只要本机 IPv4 路由表发生任何增、删、改,就立刻通知我

cpp 复制代码
IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
NotifyRouteChange(
    _Out_ PHANDLE      Handle,
    _In_  LPOVERLAPPED overlapped
    );

NotifyRouteChange 的作用可以一句话概括:
"给我一个异步事件,只要本机 IPv4 路由表发生任何增、删、改,就立刻通知我。"


1. 函数原型

c 复制代码
DWORD WINAPI NotifyRouteChange(
    _Out_ PHANDLE      Handle,     // 返回事件句柄(同步)或 NULL(异步)
    _In_  LPOVERLAPPED overlapped  // 异步 I/O 用;同步可填 NULL
);

2. 触发场景

  • 新增路由(route add、DHCP、VPN、拨号、路由协议)
  • 删除路由(route delete、接口禁用、DHCP 释放、路由老化)
  • 修改路由(Metric、网关、出接口变化)
  • 仅 IPv4 路由表 ;IPv6 需用 NotifyRouteChange2(或 NotifyIpInterfaceChange)。

3. 使用模式

模式 调用方式 等待方式
同步 Handle != NULL, overlapped == NULL WaitForSingleObject 阻塞一次
异步 Handle == NULL, 提供有效 OVERLAPPED GetQueuedCompletionStatus / 回调

4. 最小示例(同步阻塞)

cpp 复制代码
HANDLE hEvent;
DWORD ret = NotifyRouteChange(&hEvent, NULL);
if (ret == NO_ERROR) {
    wprintf(L"等待路由变化...\n");
    WaitForSingleObject(hEvent, INFINITE);
    wprintf(L"路由表已变动!\n");
    CloseHandle(hEvent);
}

5. 取消与清理

  • 同步句柄:CloseHandle(hEvent)
  • 异步:CancelIoEx(NULL, &ov) 或关闭线程池 IOCP

6. 与相关 API 对照

API 监听内容 协议 粒度
NotifyRouteChange 路由表变动 IPv4 整表
NotifyRouteChange2 路由表变动 IPv4/IPv6 可过滤地址族
NotifyAddrChange IP 地址变动 IPv4/IPv6 -
NotifyUnicastIpAddressChange 单播地址变动 IPv4/IPv6 细粒度回调

一句话总结:
NotifyRouteChange 是"路由表监视器"------注册一次,就能在 IPv4 路由发生任何变化时立即得到事件通知。

CancelIPChangeNotify:"取消"之前通过 异步方式 注册的 IP 地址或路由变化通知

cpp 复制代码
IPHLPAPI_DLL_LINKAGE
BOOL
WINAPI
CancelIPChangeNotify(
    _In_  LPOVERLAPPED notifyOverlapped
    );

CancelIPChangeNotify 用来"取消"之前通过 异步方式 注册的 IP 地址或路由变化通知

一句话:
把已经挂起的 NotifyAddrChangeNotifyRouteChange 异步请求立即撤销。


1. 函数原型

c 复制代码
BOOL WINAPI CancelIPChangeNotify(
    _In_ LPOVERLAPPED notifyOverlapped   // 指向当初传给 Notify*Change 的那个 OVERLAPPED
);
  • 返回值
    TRUE -- 成功取消
    FALSE -- 失败(调用 GetLastError 查看原因)

2. 使用场景

  • 长驻服务 / 托盘程序 在退出前,确保不再收到后续通知。
  • UI 应用 切换页面/停止监控时,避免 IOCP/线程池仍在等待。
  • 防止句柄泄漏:异步请求一旦取消,可以安全释放相关资源。

3. 典型调用流程

cpp 复制代码
OVERLAPPED gOv = {};           // 全局或成员变量
HANDLE     gIOCP = nullptr;    // 完成端口

// 1. 启动异步通知
DWORD err = NotifyAddrChange(NULL, &gOv);
if (err == ERROR_IO_PENDING) {
    // 2. 稍后在某个时刻取消
    CancelIPChangeNotify(&gOv);
}

4. 注意事项

  • 只能取消 异步模式Handle == NULL 且传了 OVERLAPPED)的请求;
    同步模式(Handle != NULL)直接用 CloseHandle 即可。
  • 取消后,对应的 OVERLAPPED 会收到一次 ERROR_OPERATION_ABORTED 完成通知。
  • CancelIoEx(NULL, &ov) 效果相同,但 CancelIPChangeNotify 语义更清晰,代码可读性更好。

一句话总结:
CancelIPChangeNotify 就是"把之前用 NotifyAddrChange / NotifyRouteChange 挂起的异步通知立即撤掉",防止程序退出后仍被系统回调。

GetAdapterIndex:把网卡的『友好名称』(Unicode 字符串) 转换成对应的接口索引 (ifIndex)

cpp 复制代码
IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
GetAdapterIndex(
    _In_    LPWSTR  AdapterName,
    _Inout_ PULONG IfIndex
    );

GetAdapterIndex 的功能一句话:
"把网卡的『友好名称』(Unicode 字符串) 转换成对应的接口索引 (ifIndex)。"


1. 函数原型

c 复制代码
DWORD WINAPI GetAdapterIndex(
    _In_    LPWSTR AdapterName,  // 输入:网卡友好名,如 L"Ethernet"
    _Inout_ PULONG IfIndex       // 输出:接口索引
);
  • 返回值
    • NO_ERROR (0) ------ 成功
    • ERROR_INVALID_PARAMETER ------ 名称空或指针空
    • ERROR_DEV_NOT_EXIST ------ 找不到该名称的接口

2. 友好名称是什么?

  • 就是你在"网络连接"窗口看到的名称,例如
    "Ethernet""Wi-Fi""vEthernet (Default Switch)"
  • 与设备管理器里的硬件描述不同,也不同于注册表里的 GUID。

3. 最小示例

cpp 复制代码
ULONG idx = 0;
DWORD ret = GetAdapterIndex(L"Ethernet", &idx);
if (ret == NO_ERROR)
    wprintf(L"Interface index of 'Ethernet' = %lu\n", idx);
else
    wprintf(L"Error: %lu\n", ret);

4. 常见用途

  • 用户界面让用户选"网卡名称",内部用索引做后续 API 调用(如 SetIpNetEntryCreateProxyArpEntry)。
  • 脚本/工具把配置文件里的可读名称转换成系统索引。
  • GetInterfaceInfo/GetAdaptersAddresses 返回的名称直接对应。

5. 注意点

  • 区分大小写:名称必须完全一致,包括空格。
  • 支持重命名 :如果用户把网卡重命名为 "LAN #2",就必须用新名称。
  • 仅限 IPv4 接口:名称必须对应已启用 IPv4 的适配器,纯 IPv6 或禁用的找不到。

一句话总结:
GetAdapterIndex 就是"把用户看得懂的网卡名字翻译成系统看得懂的接口索引"。

AddIPAddress:把指定的 IPv4 地址/掩码临时添加到某块网卡上,立刻生效,重启后失效

cpp 复制代码
IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
AddIPAddress(
    _In_ IPAddr  Address,
    _In_ IPMask  IpMask,
    _In_ DWORD   IfIndex,
    _Out_ PULONG  NTEContext,
    _Out_ PULONG  NTEInstance
    );

AddIPAddress 功能一句话

"把指定的 IPv4 地址/掩码临时添加到某块网卡上,立刻生效,重启后失效。"


1. 函数原型

c 复制代码
DWORD WINAPI AddIPAddress(
    _In_  IPAddr  Address,      // IPv4 地址(网络字节序)
    _In_  IPMask  IpMask,       // 子网掩码(网络字节序)
    _In_  DWORD   IfIndex,      // 接口索引
    _Out_ PULONG  NTEContext,   // 返回的上下文句柄
    _Out_ PULONG  NTEInstance   // 返回的实例号
);
  • 返回值
    NO_ERROR (0) 成功;其它为 Win32 错误码(如 ERROR_INVALID_PARAMETERERROR_DUP_DOMAINNAME 等)。

2. 关键概念:NTEContext / NTEInstance

  • NTEContextNTEInstance 共同构成 "网络表项句柄" ,后续调用 DeleteIPAddress 时必须原样传入才能删除这条临时地址。
  • 这两个值仅由系统生成,不要自己猜测。

3. 生命周期

  • 临时性 :地址在 当前会话 中有效,重启或禁用/启用接口后消失
  • 不写入注册表 :等同于命令行 netsh interface ip add address ... 的临时模式。
  • 可与静态/ DHCP 地址共存

4. 最小示例

cpp 复制代码
ULONG ctx, inst;
DWORD ret = AddIPAddress(
                inet_addr("192.168.50.100"),
                inet_addr("255.255.255.0"),
                7,          // 接口索引 7
                &ctx, &inst);

if (ret == NO_ERROR) {
    printf("Added temp IP 192.168.50.100/24, ctx=%lu inst=%lu\n", ctx, inst);
} else {
    printf("AddIPAddress failed: %lu\n", ret);
}

5. 删除临时地址

cpp 复制代码
DeleteIPAddress(ctx);   // 用 AddIPAddress 返回的 ctx

6. 常见错误码

错误码 说明
ERROR_INVALID_PARAMETER 地址/掩码/索引非法
ERROR_DUP_DOMAINNAME 地址已在接口上存在
ERROR_DEV_NOT_EXIST 接口索引不存在

7. 典型用途

  • 网络调试/测试:脚本快速给网卡加第二地址,用完即删。
  • VPN/代理工具:临时为 TAP 接口分配地址。
  • 零配置服务:发现冲突时可回滚。

一句话总结
AddIPAddress 是"程序级别"的临时 IPv4 地址注入器:立刻生效、重启即失,需用 DeleteIPAddress 配合清理。

DeleteIPAddress:把之前用 AddIPAddress 临时添加的 IPv4 地址立即删除

cpp 复制代码
IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
DeleteIPAddress(
    _In_ ULONG NTEContext
    );

#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */
#pragma endregion

DeleteIPAddress 的作用一句话:
把之前用 AddIPAddress 临时添加的 IPv4 地址立即删除。


函数原型

c 复制代码
DWORD WINAPI DeleteIPAddress(
    _In_ ULONG NTEContext   // 必须是 AddIPAddress 返回的 NTEContext
);
  • 返回值
    • NO_ERROR (0) ------ 删除成功
    • ERROR_INVALID_PARAMETER ------ 传入的 NTEContext 无效 / 不存在
    • 其他 Win32 错误码

使用要点

  1. 只能删除"临时地址" ------ 即通过 AddIPAddress 加入、重启会消失的地址。
  2. 必须提供 NTEContext ------ 与 AddIPAddress 返回的完全一致;不能删静态或 DHCP 地址。
  3. 立即生效 ------ 删除后接口不再拥有该地址,ARP/路由表同步更新。
  4. 无需管理员权限 ------ 只要 AddIPAddress 成功,同一进程即可删除;跨进程需权限匹配。

最小示例

cpp 复制代码
ULONG ctx, inst;
// 先添加
AddIPAddress(inet_addr("192.168.88.10"),
             inet_addr("255.255.255.0"),
             7, &ctx, &inst);

// 用完即删
DWORD ret = DeleteIPAddress(ctx);
if (ret == NO_ERROR)
    printf("Temp IP deleted.\n");
else
    printf("Delete failed: %lu\n", ret);

一句话总结:
DeleteIPAddress 就是"撤销" AddIPAddress 的专用清理函数,把临时 IPv4 地址从接口上立刻移除。

相关推荐
青草地溪水旁3 小时前
如何理解AP服务发现协议中“如果某项服务需要被配置为可通过多个不同的网络接口进行访问,则应为每个网络接口使用一个独立的客户端服务实例”?
网络·服务发现·客户端实例
门思科技3 小时前
LoRaWAN 的网络拓扑全解析:架构、原理与应用实践
服务器·网络·人工智能·科技·物联网·架构
我的收藏手册3 小时前
Linux 网络命令大全
linux·服务器·网络
焊锡与代码齐飞4 小时前
嵌入式第三十五课!!Linux下的网络编程
linux·运维·服务器·开发语言·网络·学习·算法
2501_927773075 小时前
Linux操作系统编程——网络
linux·运维·网络
武汉誉天5 小时前
学云计算还是网络,选哪个好?
网络·云计算
Johny_Zhao7 小时前
Linux防止rm误操作防护方案
linux·网络·人工智能·网络安全·信息安全·云计算·yum源·系统运维
心一信息8 小时前
如何通过华为无线控制器添加一个名为yunwei的无线网络
运维·网络·华为
废喵喵呜9 小时前
达梦数据库-实时主备集群部署详解(附图文)手工搭建一主一备数据守护集群DW
网络·数据库·tcp/ip