windows 驱动实例分析系列: wintun驱动分析-example篇(下) (接上文)二、核心代码逐段分析2.5 收发线程ReceivePackets SendPackets2.5.1 接收线程staticDWORD WINAPIReceivePackets(DWORD_PTR SessionPtr){WINTUN_SESSION_HANDLE Session(WINTUN_SESSION_HANDLE)SessionPtr;HANDLE WaitHandles[]{WintunGetReadWaitEvent(Session),QuitEvent};while(!HaveQuit){DWORD PacketSize;BYTE*PacketWintunReceivePacket(Session,PacketSize);if(Packet){PrintPacket(Packet,PacketSize);WintunReleaseReceivePacket(Session,Packet);}else{DWORD LastErrorGetLastError();switch(LastError){caseERROR_NO_MORE_ITEMS:if(WaitForMultipleObjects(_countof(WaitHandles),WaitHandles,FALSE,INFINITE)WAIT_OBJECT_0)continue;returnERROR_SUCCESS;default:LogError(LPacket read failed,LastError);returnLastError;}}}returnERROR_SUCCESS;}关键点使用WintunGetReadWaitEvent获取一个事件句柄当环形缓冲区中有新数据时该事件会被置位。若WintunReceivePacket返回ERROR_NO_MORE_ITEMS则阻塞等待事件或退出事件避免忙等浪费 CPU。收到包后调用PrintPacket打印信息然后立即WintunReleaseReceivePacket释放缓冲区以便驱动复用。2.5.2 发送线程staticDWORD WINAPISendPackets(DWORD_PTR SessionPtr){WINTUN_SESSION_HANDLE Session(WINTUN_SESSION_HANDLE)SessionPtr;while(!HaveQuit){BYTE*PacketWintunAllocateSendPacket(Session,28);if(Packet){MakeICMP(Packet);WintunSendPacket(Session,Packet);}elseif(GetLastError()!ERROR_BUFFER_OVERFLOW)returnLogLastError(LPacket write failed);switch(WaitForSingleObject(QuitEvent,1000/* 1 second */)){caseWAIT_ABANDONED:caseWAIT_OBJECT_0:returnERROR_SUCCESS;}}returnERROR_SUCCESS;}每秒构造并发送一个 28 字节的 ICMP Echo Request 包。如果发送缓冲区已满ERROR_BUFFER_OVERFLOW则静默丢弃该包这是 Wintun 推荐的做法避免阻塞。通过WaitForSingleObject(QuitEvent, 1000)实现每秒一次发送同时能及时响应退出信号。2.6 主流程mainint__cdeclmain(void){// 1. 加载 Wintun DLLHMODULE WintunInitializeWintun();if(!Wintun)returnLogError(LFailed to initialize Wintun,GetLastError());WintunSetLogger(ConsoleLogger);Log(WINTUN_LOG_INFO,LWintun library loaded);// 2. 创建退出事件和信号处理器QuitEventCreateEventW(NULL,TRUE,FALSE,NULL);SetConsoleCtrlHandler(CtrlHandler,TRUE);// 3. 创建适配器指定固定 GUIDGUID ExampleGuid{0xdeadbabe,0xcafe,0xbeef,{0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}};WINTUN_ADAPTER_HANDLE AdapterWintunCreateAdapter(LDemo,LExample,ExampleGuid);if(!Adapter){/* 错误处理 */}// 4. 获取驱动版本并打印DWORD VersionWintunGetRunningDriverVersion();Log(WINTUN_LOG_INFO,LWintun v%u.%u loaded,(Version16)0xff,(Version0)0xff);// 5. 配置 IP 地址10.6.7.7/24MIB_UNICASTIPADDRESS_ROW AddressRow;InitializeUnicastIpAddressEntry(AddressRow);WintunGetAdapterLUID(Adapter,AddressRow.InterfaceLuid);AddressRow.Address.Ipv4.sin_familyAF_INET;AddressRow.Address.Ipv4.sin_addr.S_un.S_addrhtonl((1024)|(616)|(78)|(70));AddressRow.OnLinkPrefixLength24;AddressRow.DadStateIpDadStatePreferred;LastErrorCreateUnicastIpAddressEntry(AddressRow);if(LastError!ERROR_SUCCESSLastError!ERROR_OBJECT_ALREADY_EXISTS){/* 错误处理 */}// 6. 启动 Wintun 会话容量 4MiBWINTUN_SESSION_HANDLE SessionWintunStartSession(Adapter,0x400000);if(!Session){/* 错误处理 */}// 7. 创建两个工作线程收、发HANDLE Workers[2];Workers[0]CreateThread(NULL,0,ReceivePackets,(LPVOID)Session,0,NULL);Workers[1]CreateThread(NULL,0,SendPackets,(LPVOID)Session,0,NULL);// 等待线程结束直到收到退出信号WaitForMultipleObjectsEx(2,Workers,TRUE,INFINITE,TRUE);// 8. 清理资源逆序// 结束会话、关闭适配器、释放 DLL 等}流程总结动态加载wintun.dll并获取所有函数指针。设置日志回调便于观察内部事件。创建名为Demo、类型为Example的 Wintun 适配器指定 GUID固定便于测试。为适配器分配 IP 地址10.6.7.7/24使用CreateUnicastIpAddressEntry。启动会话容量为0x4000004,194,304 字节即 4 MiB这是合理的中间值。创建接收线程和发送线程前者阻塞等待数据后者每秒发送一个 ICMP 请求。主线程等待线程结束通过 CtrlC 触发然后按顺序清理。三、项目配置文件分析3.1 example.vcxprojPropertyGroupLabelConfigurationConfigurationTypeApplication/ConfigurationTypePlatformToolsetWindowsApplicationForDrivers10.0/PlatformToolsetForcedTargetVersionWindows10/ForcedTargetVersion/PropertyGroupItemDefinitionGroupClCompileAdditionalIncludeDirectories..\api/AdditionalIncludeDirectories/ClCompileLinkAdditionalDependenciesiphlpapi.lib;kernel32.lib;ntdll.lib;ws2_32.lib;%(AdditionalDependencies)/AdditionalDependencies/Link/ItemDefinitionGroupItemGroupProjectReferenceInclude..\api\api.vcxprojProject{897f02e3-3eaa-40af-a6dc-17eb2376edaf}/Project/ProjectReference/ItemGroup关键点使用WindowsApplicationForDrivers10.0工具集使得可以链接ntdll.lib并调用NtQuerySystemTime等原生 API。添加..\api到包含目录以引用wintun.h头文件。链接iphlpapi.libCreateUnicastIpAddressEntry、InitializeUnicastIpAddressEntry、ntdll.libNtQuerySystemTime、ws2_32.lib字节序转换函数。项目引用api.vcxproj确保在构建示例前先编译wintun.dll虽然示例实际运行时动态加载但项目依赖用于生成正确的输出目录。3.2 example.vcxproj.filters只是一个标准的源文件筛选器将example.c归入“Source Files”组无特殊之处。四、编译与运行编译在 Visual Studio 中打开wintun.sln编译example项目它会自动依赖api项目生成wintun.dll。运行前准备确保wintun.dll与example.exe在同一目录或系统目录。如果驱动未安装example.exe会通过WintunCreateAdapter自动安装需要管理员权限。运行以管理员身份打开命令提示符执行example.exe。控制台会显示日志每秒发送一个 ICMP 请求并在收到回复时打印。停止按 CtrlC 触发清理程序退出。预期输出示例2026-08-10 10:00:00.1234 [] Wintun library loaded 2026-08-10 10:00:00.1256 [] Wintun v0.14 loaded 2026-08-10 10:00:01.1278 [] Sending IPv4 ICMP echo request to 10.6.7.8 from 10.6.7.7 2026-08-10 10:00:01.1301 [] Received IPv4 ICMP echo reply from 10.6.7.7 to 10.6.7.8 ...五、设计评价与教学价值5.1 优点完整生命周期从 DLL 加载、适配器创建、IP 配置、数据收发到优雅退出覆盖了所有关键 API。健壮的错误处理每步操作都检查返回值并通过日志输出详细错误信息。多线程示范展示了如何并发处理收发包以及如何利用事件对象协调线程。自包含测试通过构造 ICMP 包并回环接收无需外部设备即可验证驱动功能。清晰的代码风格函数职责单一注释虽少但命名自解释。5.2 教学意义可作为新手入门 Wintun 的第一份代码快速理解 API 用法。展示了 Windows 网络编程中的常见模式延迟加载 DLL、错误码格式化、控制台信号处理、IP 地址配置。可扩展为实际 VPN 客户端的骨架只需修改MakeICMP为隧道数据封装并添加路由表操作。5.3 潜在改进点发送线程固定每秒一个包实际应用可能需要动态调整速率。未处理 IPv6 情况虽然接收端支持但发送端只构造 IPv4。未展示如何设置默认网关或路由表这对 VPN 是必需的。六、总结example文件夹虽然仅包含一个源文件但它浓缩了 Wintun 使用的所有精华。它不仅是项目的“门面示例”更是 WireGuard 团队为开发者精心准备的可工作的最小原型。通过这个示例开发者可以快速搭建起自己的隧道应用而无需从头研究 Windows 网络栈的复杂细节。评价这是一个教科书级别的示例程序兼具实用性和教学性值得所有 Windows 网络开发者学习和借鉴。

相关新闻

最新新闻

微信聊天记录导出没那么难:WeChatMsg让十年对话永久保存,全程10分钟

微信聊天记录导出没那么难:WeChatMsg让十年对话永久保存,全程10分钟

微信聊天记录导出没那么难:WeChatMsg让十年对话永久保存,全程10分钟 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/…

2026/8/13 11:24:32
双目测距核心原理与工程实践:从视差公式到深度图生成

双目测距核心原理与工程实践:从视差公式到深度图生成

1. 双目测距:从三维世界到二维图像的数学解码当你用双眼看世界时,能轻易判断出远处那棵树离你有多远,桌上的水杯伸手就能够到。这种与生俱来的深度感知能力,其背后的原理,正是双目视觉的核心。在计算机视觉领域&#x…

2026/8/13 11:24:32
C语言实现二叉树:从结构体定义到遍历与搜索算法详解

C语言实现二叉树:从结构体定义到遍历与搜索算法详解

1. 从“树”到“二叉树”:一个更高效的存储模型 在编程世界里,数据结构的选择往往决定了程序的效率和优雅程度。当我们谈论线性结构,比如数组或链表时,它们像一条单行道,数据元素一个接一个地排列。这种结构在处理“一…

2026/8/13 11:24:32
如何快速实现微信批量添加好友:面向运营人员和销售人员的完整指南

如何快速实现微信批量添加好友:面向运营人员和销售人员的完整指南

如何快速实现微信批量添加好友:面向运营人员和销售人员的完整指南 【免费下载链接】auto_add_wechat_friends_py 微信添加好友 批量发送添加请求 脚本 python 项目地址: https://gitcode.com/gh_mirrors/au/auto_add_wechat_friends_py 你是否曾经为手动添加…

2026/8/13 11:24:32
K8s节点异常诊断与修复实战:从NotReady到自动化运维

K8s节点异常诊断与修复实战:从NotReady到自动化运维

1. 项目概述:当K8s节点“生病”了怎么办? 在K8s集群的日常运维中,节点异常是每个管理员迟早都会面对的“必修课”。想象一下,你正悠闲地喝着咖啡,监控大盘上突然亮起一片刺眼的红色告警,某个工作节点&#…

2026/8/13 11:24:32
软考系统架构师论文真题解析与高分写作指南(2009-2024)

软考系统架构师论文真题解析与高分写作指南(2009-2024)

1. 项目概述:一份“过来人”的论文题库与实战心法 如果你正在备考软考高级系统架构设计师,或者对这个“含金量”颇高的认证感兴趣,那么“论文”这个科目,大概率是你心头最大的那块石头。它不像选择题有标准答案,也不像…

2026/8/13 11:19:32