模块契约网络接口

错误

本文件与 net.md 共享 include/xrt/net_interface.h 的错误体系;失败经 xrtGetError() 报告:

域/种类触发场景
XERR_ARGUMENT / XERR_RANGE参数与索引越界
XERR_NOT_FOUND指定接口或地址不存在
XERR_IO系统接口枚举失败
xrt.net / XNET_ERROR_INTERFACE_*接口地址、硬件等平台查询失败

分层

XRT_FEATURE_NET_INTERFACE 只依赖网络地址基础层,公开头文件为 <xrt/net_interface.h>。它负责接口名称与索引互转、接口快照、MTU、硬件地址、 接口标志、单播地址和前缀长度,不引入 Socket、Engine、线程、DNS 或容器。

启用该模块后,xrtNetAddrParse 和 xrtNetAddrParseEndpoint 同时接受 IPv6 数字 Scope 与接口名称 Scope,例如 fe80::1%eth0 和 [fe80::1%eth0]:8080。解析结果仍只保存稳定的数字接口索引, xrtNetAddrText 因此保持无系统查询的规范数字输出。

名称与索引

Windows 的规范名称来自系统适配器名称,显示名称是 UTF-8 接口别名;POSIX 两者 都是 if_name。xrtNetInterfaceIndex 同时接受规范名称和显示名称。 Windows 分别保存 IPv4 与 IPv6 索引;POSIX 两者通常相同。UNSPEC 查询优先 IPv6 索引,再使用 IPv4 索引。

索引零不是有效结果。找不到名称或索引时分别报告 XNET_ERROR_INTERFACE_INDEX 与 XNET_ERROR_INTERFACE_NAME。 xrtNetInterfaceName 与其他文本 API 一样支持空输出测量;缓冲不足时安全截断、 补零、返回完整所需长度并报告 XNET_ERROR_BUFFER。

接口快照

快照使用一次 XRT 分配保存接口数组、地址数组、名称和硬件地址。所有视图都借用 快照,释放后立即失效;Free 可对空列表重复调用。失败不会修改输出。 接口和地址顺序由操作系统决定,调用方不得把顺序当作身份。

PrefixLength 为 IPv4 的 0..32 或 IPv6 的 0..128;平台不能可靠提供连续 掩码时使用 XNET_INTERFACE_PREFIX_UNKNOWN。地址端口恒为零。链路本地 IPv6 地址缺少原生 Scope 时,快照使用该接口的 IPv6 索引补齐。

标志只暴露跨平台稳定交集:UP、RUNNING、LOOPBACK、BROADCAST、 POINT_TO_POINT 和 MULTICAST。某个平台没有可靠来源的标志保持未设置, 不能把未设置解释为能力一定不存在。

本机信息便捷层

xrtNetLocalAddress 从接口快照中选择适合启动日志、节点报告和诊断页展示的 单播地址。它依次偏好 UP、RUNNING、非回环、非链路本地接口;条件相同时 UNSPEC 优先 IPv6。该结果不是公网出口地址,也不代表系统默认路由,不能直接 替代服务监听、客户端源地址或多网卡路由策略。需要精确选择时应遍历 xrtNetInterfaces。

xrtNetLocalHardware 返回原始硬件地址,不把地址长度写死为 6 字节。空输出和零 容量只查询所需大小;缓冲不足时不写入,返回完整所需大小并报告 XNET_ERROR_BUFFER。没有带有效硬件地址的接口时报告 XNET_ERROR_INTERFACE_HARDWARE。

xrtNetHostName 使用动态平台缓冲读取完整主机名。它支持空输出测量;缓冲不足时 安全截断、补零并返回完整所需长度。主机名只是本机标签,不保证能够通过 DNS 解析,也不等于 HTTP Host、TLS SNI 或服务绑定名。

文本便捷函数

启用 XRT_FEATURE_NET_INTERFACE_TEXT 后可以直接使用:

String 函数返回由 xrtFree 释放的字符串。硬件地址文本使用大写、无分隔符的 紧凑 HEX;需要冒号、短横线或其他展示格式时应读取原始字节后自行格式化。 文本层依赖 NET_INTERFACE 与 CODEC_HEX,基础接口快照和二进制便捷查询不会 因此引入 HEX 编解码。

裁剪与依赖

只选择 XRT_MODULE_NET_INTERFACE 时不会带入 TCP、UDP、异步运行时或 HTTP。 XRT_MODULE_NET_INTERFACE_TEXT 是独立裁剪的小型易用层。 模块测试只枚举本机系统接口并解析本机接口名称,不发送报文,也不访问外部地址。 底层示例位于 examples/network/interface/main.c,便捷层示例位于 examples/network/local_info/main.c。

设计契约

XRT_FEATURE_NET 是网络体系最底层的独立裁剪单元,只依赖 core。这一层不创建 Socket,不执行 DNS,也不依赖线程、任务或协程;它负责稳定的 IP 地址表示、数字地址与端点解析、规范输出、地址分类和平台 sockaddr 转换。

公开头文件不包含 Winsock 或 POSIX Socket 头文件。xnetaddr 因此可以直接进入 FFI 值类型、容器键、配置结构和协议对象,不会把平台 ABI 扩散到上层。Windows 网络运行时由后续 Socket 操作按需初始化,使用者不需要配对调用启动与清理函数。

Port 使用主机字节序,Address 始终使用网络字节序。IPv4 只使用前 4 字节;Scope 只对 IPv6 有意义。地址族常量是 XRT 自己的稳定值,不能与 AF_INET、AF_INET6 混用。

网络缓冲

XRT_FEATURE_NET_BUFFER 依赖 XRT_FEATURE_NET,提供 TCP、UDP、TLS、HTTP 和 WebSocket 共用的可变尺寸缓冲底座。缓冲只在实际收到或排队数据时持有块;默认池尺寸类为 512、2048、8192、32768 字节,超过最大类的请求按实际大小单独分配;默认总缓存硬上限 2 MiB 且缓存属于 Worker 而非连接——一万个空闲连接不会因此各自占用 8K。

线程:池与缓冲是线程归属对象,不在热路径加锁;同一时刻只能由所属 Worker 操作。跨线程长期保存数据时使用不绑定池的缓冲(Init 传空池)、复制到调用方内存,或让所属 Worker 执行最终释放。

所有权:四种追加形态按复制/借用/接管/自定义释放区分;Take/Ref 只有成功才转移所有权,失败时数据仍归调用方。xnetspan 只借用块内数据——任何追加、提交、消费、Pullup、Move 或 Clear 后必须重新获取。

地址列表与 DNS

数字地址语法不包含主机名解析;DNS 与不可变地址列表属于 XRT_FEATURE_NET_DNS。列表是解析结果的不可变共享快照:复制、校验、去重调用方地址后建立,Ref 增引用、Destroy 配对释放,端口统一替换用 WithPort。

网络缓冲

XRT_FEATURE_NET_BUFFER 依赖 XRT_FEATURE_NET,提供 TCP、UDP、TLS、HTTP 和 WebSocket 共用的可变尺寸缓冲底座。它保留旧版 xnetchain 的分块、Span 和引用数据优势,但删除“每个连接常驻固定 8K 缓冲”的模型。

缓冲只在实际收到或排队数据时持有块。默认池尺寸类为 512、2048、8192、32768 字节;超过最大类的请求按实际大小单独分配。默认总缓存硬上限为 2 MiB,并且缓存属于 worker,而不是连接:一万个空闲连接不会因此各自占用 8K。

Socket 原语

XRT_FEATURE_NET_SOCKET 只依赖 XRT_FEATURE_NET。这一层拥有平台 Socket 句柄,但不包含事件循环、线程、协程、隐藏收发缓冲、TCP 重连或 UDP 队列;TCP/UDP 客户端与服务器模型在它和事件端口之上组合。

错误与线程:收发族返回 xnetresult 三态(OK/AGAIN/CLOSED/ERROR),系统调用失败经 xrtGetError() 报告且保留平台错误码(XNET_ERROR_SOCKET_* 域码 + SystemCode)。Socket 无内部锁——同一 Socket 的收发应由单执行流执行;xnetsocket 是不透明指针,句柄值可为 0(视同空)。NATIVE 后缀在 Windows 上即 IOCP 兼容句柄。

网络事件端口

XRT_FEATURE_NET_PORT 依赖 Socket、单调截止时间和 Mutex,提供 backend-neutral 事件端口核心;具体后端使用独立裁剪宏。XRT_FEATURE_NET_PORT_SELECT 提供全平台 select fallback,XRT_FEATURE_NET_PORT_EPOLL 提供 Linux 原生 readiness,XRT_FEATURE_NET_PORT_KQUEUE 提供 Darwin/BSD 原生 readiness,XRT_FEATURE_NET_PORT_IOCP 提供 Windows 原生完成式 IO,XRT_FEATURE_NET_PORT_URING 提供 Linux 原生完成式 IO。readiness 与 completion 使用同一组事件、截止时间、错误和所有权口径,但不会被强迫伪装成相同执行模型。

端口由创建线程拥有:Watch、提交、取消、等待和销毁只能由拥有线程执行;查询函数以及 Post、Wake 可跨线程调用,调用方仍须保证端口对象存活。

嵌入式任务投递

xnetpost 是嵌入调用方结构的无分配任务节点:xrtNetPostInit 初始化,xrtNetPost 投递到指定 Worker 队列,出队前 xrtNetPostPending 为真。与 xrtNetEnginePost 相比它不分配节点,适合高频、固定生命周期的任务;同一 xnetpost 在出队并执行完成前不能再次投递。调用方必须通过网络对象引用保证 Worker 和 xnetpost 存活到回调返回。

网络 Engine

启用 XRT_FEATURE_NET_ENGINE 后,Engine 在事件端口之上提供固定 Worker、 有界跨线程命令、可取消 Timer 和统一 Completion 分发。它不实现 TCP、UDP、DNS 或应用协议,因此自定义传输与 XRT 高层传输可以建立在同一套运行时契约上。

标准 Engine 的平台闭包为 Windows IOCP + select、Linux epoll + select、Darwin/BSD kqueue + select、其他 POSIX 平台当前 select。Linux 的精细裁剪构建也允许 io_uring + select,不要求同时编入 epoll;此时调用方必须显式选择 XNET_PORT_URING,AUTO 仍只在已经编译的稳定默认后端中选择。显式 XNET_PORT_SELECT 可用于受限环境、诊断和后端差异回归;具体端口后端仍可脱离 Engine 独立裁剪。

名称解析(Resolver)

Resolver 提供独立于 Engine 的异步名称解析:自带工作线程池、成功/失败结果缓存与并发上限。同一规范化主机与地址族只执行一次底层查询,并发请求共享同一查询组。xrtNetResolveAsync 把查询包装为 Future。Op(xnetresolveop)是引用计数对象:回调在 Resolver Worker 上恰好执行一次,回调后仍可查询状态与结果,跨线程保留须先 xrtNetResolveOpRef。

网络接口与本机信息

接口族回答三类问题:名字与接口索引互查(InterfaceIndex/InterfaceName)、整机一致快照(Interfaces)、本机诊断偏好(LocalAddress/LocalHardware/HostName 及其文本形态)。本机诊断函数是确定性偏好查询,不代表公网出口、默认路由或服务监听策略。缓冲输出统一采用两段式:空缓冲查询所需大小,缓冲不足不写入并报告完整所需大小。

xnetinterfaceflag类型

接口标志只表达跨平台能够稳定观察的状态和能力。

值语义
XNET_INTERFACE_UP接口在线
XNET_INTERFACE_RUNNING运行中
XNET_INTERFACE_LOOPBACK回环接口
XNET_INTERFACE_BROADCAST广播
XNET_INTERFACE_POINT_TO_POINT点对点链路
XNET_INTERFACE_MULTICAST支持多播
typedef enum xnetinterfaceflag { XNET_INTERFACE_UP = 0x0001, XNET_INTERFACE_RUNNING = 0x0002, XNET_INTERFACE_LOOPBACK = 0x0004, XNET_INTERFACE_BROADCAST = 0x0008, XNET_INTERFACE_POINT_TO_POINT = 0x0010, XNET_INTERFACE_MULTICAST = 0x0020 } xnetinterfaceflag;

xnetinterfaceaddress类型

接口地址不带传输端口,PrefixLength 为网络前缀位数。

字段类型语义
Addressxnetaddr地址
PrefixLengthuint8PrefixLength
typedef struct xnetinterfaceaddress { xnetaddr Address; uint8 PrefixLength; } xnetinterfaceaddress;

xnetinterface类型

名称、硬件地址和地址数组均借用所属接口快照。

字段类型语义
IPv4Indexuint32IPv4Index
IPv6Indexuint32IPv6Index
Flagsuint32标志位
Mtuuint32最大传输单元
Namexstrview名称
DisplayNamexstrviewDisplayName
HardwareAddressxbytesviewHardwareAddress
Addressesconst xnetinterfaceaddress*Addresses
AddressCountsize_tAddressCount
typedef struct xnetinterface { uint32 IPv4Index; uint32 IPv6Index; uint32 Flags; uint32 Mtu; xstrview Name; xstrview DisplayName; xbytesview HardwareAddress; const xnetinterfaceaddress* Addresses; size_t AddressCount; } xnetinterface;

xnetinterfacelist类型

接口列表拥有 Items 以及所有条目借用的存储。

字段类型语义
Itemsconst xnetinterface*元素数组
Countsize_t数量
typedef struct xnetinterfacelist { const xnetinterface* Items; size_t Count; } xnetinterfacelist;

xrtNetInterfaceIndex函数

把规范名称或显示名称转换为接口索引。UNSPEC 优先返回 IPv6 索引,再返回 IPv4 索引;失败返回零。

uint32 xrtNetInterfaceIndex(cstr sName, xnetfamily Family)

参数

参数方向约束说明
sName输入非空规范名或系统显示名(Windows 为显示名)
Family输入地址族UNSPEC 两族都匹配,优先 IPv6
返回值
返回含义失败时状态
非 0接口索引—
0未找到或系统查询失败错误经 xrtGetError() 报告
错误
  • XERR_NOT_FOUND + XNET_ERROR_INTERFACE_INDEX — 没有该名称的接口
  • XERR_IO + XNET_ERROR_INTERFACE_INDEX — 系统接口查询失败

范例已编译验证

network/interface_tour · 往返 · 跨平台回环命名差异

iIndex = xrtNetInterfaceIndex("loopback4", XNET_FAMILY_IPV4);
if ( iIndex == 0u ) {
	iIndex = xrtNetInterfaceIndex(
		"Loopback Pseudo-Interface 1", XNET_FAMILY_IPV4);
}

xrtNetInterfaceName函数

输出指定接口索引的规范名称并返回所需长度。UNSPEC 同时匹配 IPv4 与 IPv6 索引;空输出可查询所需大小。

size_t xrtNetInterfaceName(uint32 iIndex, xnetfamily Family, char* sName, size_t iCapacity)

参数

参数方向约束说明
iIndex输入非零接口索引
Family输入地址族指定匹配哪族索引;UNSPEC 两族都试
sName输出可空输出缓冲;空指针表示只查所需大小
iCapacity输入—缓冲容量(含结尾零字节)
返回值
返回含义失败时状态
> 0不含结尾零的所需长度;缓冲足够时已写入—
0索引未找到错误经 xrtGetError() 报告
错误
  • XERR_NOT_FOUND + XNET_ERROR_INTERFACE_NAME — 没有该索引的接口
  • XERR_RANGE + XNET_ERROR_BUFFER — 缓冲不足:不写入,返回完整所需大小

范例已编译验证

network/interface_tour · 往返 · 两段式:先查大小再写入

iNeed = xrtNetInterfaceName(iIndex, XNET_FAMILY_IPV4, NULL,
	0u);
if ( (iNeed == 0u) || (iNeed >= sizeof(sName)) ) {
	goto Cleanup;
}
iSize = xrtNetInterfaceName(iIndex, XNET_FAMILY_IPV4, sName,
	sizeof(sName));

xrtNetInterfaces函数

创建当前系统接口、地址和元数据的一致快照。

bool xrtNetInterfaces(xnetinterfacelist* pList)

参数

参数方向约束说明
pList输出非空接收拥有型快照;用后 InterfacesFree 释放
返回值
返回含义失败时状态
true快照已写入(Items/Count 与每接口地址数组)—
false参数非法或系统查询/分配失败错误经 xrtGetError() 报告
错误
  • XERR_ARGUMENT — pList 为空
  • XERR_IO — 系统接口枚举失败
  • 内存分配失败 — 快照存储分配失败

范例已编译验证

network/interface · 枚举 · 遍历接口与地址前缀

if ( !xrtNetInterfaces(&List) ) {
	return 1;
}
for ( i = 0; i < List.Count; i++ ) {
	const xnetinterface* pInterface = &List.Items[i];

xrtNetInterfacesFree函数

释放接口快照拥有的全部存储并清零。

void xrtNetInterfacesFree(xnetinterfacelist* pList)

参数

参数方向约束说明
pList输入允许空指针Interfaces 产物;释放后清零可复用
返回值
返回含义
无空指针是空操作

范例已编译验证

network/interface · 枚举 · 用后释放

xrtNetInterfacesFree(&List);
return 0;
}

xrtNetLocalAddress函数

选择一个适合本机诊断的单播地址。这是确定性偏好查询,不代表公网出口、默认路由或服务监听策略。

bool xrtNetLocalAddress(xnetaddr* pAddress, xnetfamily Family)

参数

参数方向约束说明
pAddress输出非空接收地址;端口为零
Family输入IPV4/IPV6/UNSPEC期望族;UNSPEC 按平台偏好选择
返回值
返回含义失败时状态
true已写入偏好地址—
false参数非法或无可用地址错误经 xrtGetError() 报告
错误
  • XERR_ARGUMENT — pAddress 为空或 Family 非法
  • XERR_NOT_FOUND + XNET_ERROR_INTERFACE_ADDRESS — 没有可用的本机单播地址

范例已编译验证

network/interface_tour · 本机信息 · 结构体出参形态

if ( !xrtNetLocalAddress(&Address, XNET_FAMILY_IPV4) ||
	(Address.Family != XNET_FAMILY_IPV4) ||
	(Address.Port != 0u) ) {
	goto Cleanup;
}

xrtNetLocalAddressText函数

输出首选本机地址文本并返回不含结尾零字节的所需长度。

size_t xrtNetLocalAddressText(xnetfamily Family, char* sAddress, size_t iCapacity)

参数

参数方向约束说明
Family输入地址族期望族
sAddress输出可空输出缓冲;空指针表示只查所需大小
iCapacity输入—缓冲容量(含结尾零字节)
返回值
返回含义失败时状态
> 0不含结尾零的所需长度;缓冲足够时已写入—
XRT_NPOS无可用本机地址错误经 xrtGetError() 报告(NOT_FOUND 族)
错误
  • 同 xrtNetLocalAddress — 地址选择失败时透传(NOT_FOUND + INTERFACE_ADDRESS)

范例已编译验证

network/interface_tour · 本机信息 · 两段式文本输出

iNeed = xrtNetLocalAddressText(XNET_FAMILY_IPV4, NULL, 0u);
if ( (iNeed == 0u) || (iNeed >= sizeof(sText)) ) {
	goto Cleanup;
}
iSize = xrtNetLocalAddressText(XNET_FAMILY_IPV4, sText,
	sizeof(sText));

xrtNetLocalAddressString函数

分配并返回首选本机地址文本。

str xrtNetLocalAddressString(xnetfamily Family)

参数

参数方向约束说明
Family输入地址族期望族
返回值
返回含义失败时状态
非空xrtAlloc 分配的文本,调用方 xrtFree—
NULL无可用地址或分配失败不设置线程错误(查询语义)
错误
  • 无 — NULL 表示本机无可用地址或分配失败,调用方判空即可

范例已编译验证

network/local_info · 一览 · 启动日志三件套之一

str sAddress = xrtNetLocalAddressString(XNET_FAMILY_UNSPEC);
str sHost = xrtNetHostNameString();
str sHardware = xrtNetLocalHardwareString();

xrtNetLocalHardware函数

输出首选活动接口的原始硬件地址并返回所需字节数。空输出可查询大小;缓冲不足时不写入并报告完整所需大小。

size_t xrtNetLocalHardware(void* pAddress, size_t iCapacity)

参数

参数方向约束说明
pAddress输出可空输出缓冲;空指针表示只查所需大小
iCapacity输入—缓冲容量(字节)
返回值
返回含义失败时状态
> 0所需字节数(典型 MAC 为 6);缓冲足够时已写入—
0无可用硬件地址错误经 xrtGetError() 报告
错误
  • XERR_NOT_FOUND + XNET_ERROR_INTERFACE_HARDWARE — 没有可用的本机硬件地址
  • XERR_RANGE + XNET_ERROR_BUFFER — 缓冲不足:不写入,返回完整所需大小

范例已编译验证

network/interface_tour · 本机信息 · 原始字节两段式

iNeed = xrtNetLocalHardware(NULL, 0u);
if ( (iNeed < 6u) || (iNeed > sizeof(Hardware)) ) {
	goto Cleanup;
}
iSize = xrtNetLocalHardware(Hardware, sizeof(Hardware));

xrtNetLocalHardwareText函数

输出首选接口硬件地址的大写紧凑 HEX 文本。

size_t xrtNetLocalHardwareText(char* sAddress, size_t iCapacity)

参数

参数方向约束说明
sAddress输出可空输出缓冲;空指针表示只查所需大小
iCapacity输入—缓冲容量(含结尾零字节)
返回值
返回含义失败时状态
> 0不含结尾零的所需长度(6 字节 MAC 为 12 字符)—
0无可用硬件地址错误经 xrtGetError() 报告
错误
  • XERR_NOT_FOUND — 无可用硬件地址(透传 LocalHardware)
  • XERR_RANGE + XNET_ERROR_BUFFER — 缓冲不足:不写入,返回完整所需大小

范例已编译验证

network/interface_tour · 本机信息 · 6 字节 MAC → 12 个 HEX 字符

iNeed = xrtNetLocalHardwareText(NULL, 0u);
if ( (iNeed < 12u) || (iNeed >= sizeof(sText)) ) {
	goto Cleanup;
}
iSize = xrtNetLocalHardwareText(sText, sizeof(sText));

xrtNetLocalHardwareString函数

分配并返回首选接口硬件地址的大写紧凑 HEX 文本。

str xrtNetLocalHardwareString()

参数

参数方向约束说明
无——取首选活动接口
返回值
返回含义失败时状态
非空xrtAlloc 分配的文本,调用方 xrtFree—
NULL无可用硬件地址或分配失败(如纯回环环境)不设置线程错误(查询语义)
错误
  • 无 — NULL 表示不可用,调用方判空即可

范例已编译验证

network/local_info · 一览 · 判空后回退占位文本

str sAddress = xrtNetLocalAddressString(XNET_FAMILY_UNSPEC);
str sHost = xrtNetHostNameString();
str sHardware = xrtNetLocalHardwareString();

xrtNetHostName函数

输出本机主机名并返回不含结尾零字节的所需长度。

size_t xrtNetHostName(char* sName, size_t iCapacity)

参数

参数方向约束说明
sName输出可空输出缓冲;空指针表示只查所需大小
iCapacity输入—缓冲容量(含结尾零字节)
返回值
返回含义失败时状态
> 0不含结尾零的所需长度;缓冲足够时已写入—
0系统查询失败错误经 xrtGetError() 报告
错误
  • XERR_IO — 系统主机名查询失败
  • XERR_RANGE + XNET_ERROR_BUFFER — 缓冲不足:不写入,返回完整所需大小

范例已编译验证

network/interface_tour · 本机信息 · 两段式输出

iNeed = xrtNetHostName(NULL, 0u);
if ( (iNeed == 0u) || (iNeed >= sizeof(sName)) ) {
	goto Cleanup;
}
iSize = xrtNetHostName(sName, sizeof(sName));

xrtNetHostNameString函数

分配并返回本机主机名。

str xrtNetHostNameString()

参数

参数方向约束说明
无——查询系统主机名
返回值
返回含义失败时状态
非空xrtAlloc 分配的文本,调用方 xrtFree—
NULL系统查询或分配失败不设置线程错误(查询语义)
错误
  • 无 — NULL 表示不可用,调用方判空即可

范例已编译验证

network/local_info · 一览 · 三件套打印后统一释放

str sAddress = xrtNetLocalAddressString(XNET_FAMILY_UNSPEC);
str sHost = xrtNetHostNameString();
str sHardware = xrtNetLocalHardwareString();

常量索引常量

以下常量在本页所属头文件中定义,语义见公共头注释。

常量说明
XNET_INTERFACE_BROADCAST见头文件注释
XNET_INTERFACE_LOOPBACK见头文件注释
XNET_INTERFACE_MULTICAST见头文件注释
XNET_INTERFACE_POINT_TO_POINT见头文件注释
XNET_INTERFACE_PREFIX_UNKNOWN见头文件注释
XNET_INTERFACE_RUNNING见头文件注释
XNET_INTERFACE_UP见头文件注释