WSASTARTUP
定义
WSASTARTUP是Windows套接字(Winsock)接口提供的一个初始化函数,作用是在进程内启动对Winsock动态链接库的使用。它属于Winsock API中带WSA前缀的一组函数,Winsock接口本身以BSD套接字接口为基础,并为Windows的消息驱动模型作了扩展。[1][3]
函数原型为 int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)。第1个参数是调用方能够使用的Windows套接字规范最高版本,其中低序字节写主版本号、高序字节写次版本号,通常由MAKEWORD宏生成,例如MAKEWORD(2,2)表示请求2.2版;第2个参数是输出用的WSADATA结构指针,用于接收实现方返回的版本与实现细节。[1][2]
函数成功时返回0,失败时返回错误码,常见的有WSASYSNOTREADY、WSAVERNOTSUPPORTED、WSAEPROCLIM、WSAEFAULT等,分别对应网络子系统未就绪、请求版本不被支持、任务数达到上限和指针无效等情况。错误码由函数直接返回,调用方不需要也不应改用WSAGetLastError读取,因为失败时Winsock库可能尚未装载,存放最近错误信息的数据区还不存在。[2][1]
原理
调用WSASTARTUP时,Winsock库首先检查调用方请求的版本。只要请求版本不低于库所支持的最低版本,调用即成功,库把自身支持的最高规范版本写入WSADATA的wHighVersion成员,并把该最高版本与请求版本中较小的一个写入wVersion成员,作为预期调用方使用的版本。如果调用方不接受返回的wVersion,应当调用WSACleanup释放资源并放弃初始化。[2]
除版本协商外,该函数还完成与套接字使用相关的进程级准备工作:Winsock动态链接库被装入进程,库内许多按进程建立、对应用不可见的内部结构被初始化,这些结构在后续每一次套接字调用中都会被访问。因此每个使用套接字的进程都要为自身内存空间执行一次初始化,并在结束时做对应清理。
版本协商的判定可用下式概括:$wVersion = \min(wHighVersion,\ wVersionRequested)$,前提是 $wVersionRequested \ge$ 库支持的最低版本,否则调用返回失败。这种机制使库与应用只需在版本区间上有交集即可配合工作,也保证了为较低版本编写的程序能在新库上以原有行为运行。[2]
graph TD
A[应用调用 WSAStartup 并传入请求版本] --> B{请求版本不低于库支持的最低版本?}
B -- 否 --> C[返回 WSAVERNOTSUPPORTED 等错误码]
B -- 是 --> D[写入 wHighVersion 与 wVersion]
D --> E{调用方接受 wVersion?}
E -- 否 --> F[调用 WSACleanup 释放资源]
E -- 是 --> G[装载 Winsock DLL 并初始化进程内结构]
G --> H[可调用其他 Winsock 函数]
多个函数调用之间存在配对关系。按照规范,每一次成功的WSASTARTUP调用都要对应一次WSACleanup调用:若程序调用了3次WSAStartup,就需调用3次WSACleanup,前两次只把内部计数器减1,最后一次才真正释放任务占用的资源。这种引用计数设计使多个模块或第三方库可以在同一进程中各自初始化套接字而互不干扰。[4][5]
发展历程
Winsock规范源于1991年10月在Interop展会期间的一次讨论,最初的规范文本由Martin Hall、Mark Towfiq、Geoff Arnold、Henry Sanders等人编写。第1版规范于1992年6月发布,1.1版于1993年1月发布,后者以大量小修正与澄清为主,并加入了gethostname()函数。[3][6]
WSASTARTUP作为每个Winsock程序使用前的强制性调用,其版本协商参数也随之与规范版本同步。Winsock 2在1.1基础上做了向后兼容的扩展,增加了与协议无关的名字解析、基于事件的异步通知、多播和服务质量等功能;2.1.0版于1996年1月成为Winsock 2规范首次公开发布的版本,2.2.0版于1996年5月发布,并且是首个不再支持16位Windows程序的版本。[3]
现行Windows套接字规范的版本为2.2,当前Winsock库Ws2_32.dll可以接受请求1.0、1.1、2.0、2.1、2.2等版本的应用程序。Windows 95、Windows NT 3.51及更早的系统最高只支持1.1版,而Windows 95 OSR2及之后的系统普遍支持2.2版。微软已不再单独提供早期的16位套接字库,调用方式与头文件随之由winsock.h转向winsock2.h。[1][3]
应用
任何在Windows上使用套接字的程序,无论是客户端还是服务端,都要在执行绑定、连接、收发等操作前调用WSASTARTUP完成库的初始化;未做这一步就调用其他Winsock函数会得到WSANOTINITIALISED错误。典型写法是声明一个WSADATA变量,以MAKEWORD(2,2)为参数调用该函数,并根据返回值判断初始化是否成功、随后核对wVersion是否符合预期。
在工程实践中,该调用常被放在程序入口处或封装的套接字类构造过程中,退出时对应调用WSACleanup。由于库按进程维度的任务维护引用计数,多个组件各自初始化时只要保证调用次数与清理次数一一对应即可。上层网络库与跨平台适配层在Windows平台上也会代为执行这一初始化,使调用方无需直接处理库的装载。[4][7]
局限
WSASTARTUP只完成套接字库的装载与版本协商,不建立任何网络连接,也不校验网络是否可用。它返回成功仅表示初始化与协商通过,底层网络子系统此后可能仍然不可用,因此后续的绑定、连接等操作需各自处理错误。[1]
版本协商本身也有边界。为较低版本编写的程序即使与新库协商成功,也只保证能使用该版本语法范围内的功能,新函数可能无法访问;要完全使用更高版本的新语法,程序必须按该版本的规范编译并链接相应的头文件与库。此外,规范规定同一任务内各次WSAStartup调用的请求版本被视为相同,程序不能在首次调用之后更换所期望的套接字版本。[2][8]
调用与清理次数不配对会带来副作用。WSACleanup比WSAStartup多调用一次可能影响该程序在所有线程上的套接字操作,而完全不做清理则依赖进程终止时由系统回收资源。在多线程环境中,这类以进程级计数器管理生命周期的方式需要额外同步,通常由上层封装统一管理。[9][4]
参见
-
Windows套接字 —— 本函数所属的网络编程接口规范及其版本体系。
-
WSACleanup —— 与WSAStartup配对使用的清理函数,负责递减引用计数并释放资源。
-
WSADATA —— 接收版本号与实现细节的输出结构。
-
WSAGetLastError —— 用于获取其他Winsock函数错误码的接口。
-
Berkeley套接字 —— Winsock接口设计与命名所依据的套接字标准。
参考资料
- WSAStartup 函数 (winsock.h) [引用日期2026-10-29]
- WSAStartup - 跳至主要内容 跳到 Ask Learn 聊天体验 [引用日期2026-10-29]
- Winsock [引用日期2026-10-29]
- WSAStartup with RAII [引用日期2026-10-29]
- 200505051637.j45Gbem28950@candle.pha.pa [引用日期2026-10-29]
- Winsock [引用日期2026-10-29]
- wsa [引用日期2026-10-29]
- EP0770958A1(PDF) [引用日期2026-10-29]
- Revision b7e3e49e-a445-40c4-8580-718172257b25 [引用日期2026-10-29]