每个Winsock应用程序必须导入合适版本的Winsock DLL。如果在调用Winsock函数之前导入库函数失败,则函数会返回SOCKET_ERROR,该错误值是WSANOTINITIALISED。通过调用WSAStartup()函数来导入Winsock库文件。
1 WSAStartup()函数
WSAStartup()函数的格式如下所示
int WSAStartup( WORD wVersionRequired, LPWSADATA lpWSAData );
其中,wVersionRequired用来指定要导入的Winsock库文件的版本号;高阶字节指定了版本号中较小的数字(小数点之后的数字),低阶字节指定了版本号中较大的数字(小数点之前的数字)。可以使用MAKEWORD(x,y)宏来创建Winsock的版本号,其中x表示高阶字节,而y表示低阶字节。lpWSAData是WSADATA结构的指针,该参数在调用WSAStartup()函数后会将其成员变量进行填充。
2 WSADATA结构
WSADATA结构定义如下所示
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char *lpVendorInfo;
char szDescription[WSADESCRIPTION_LEN + 1];
char szSystemStatus[WSASYS_STATUS_LEN + 1];
} WSADATA;
WSAStartup()函数将第一个成员变量wVersion设置为要使用的Winsock的版本号;wHighVersion保存了Winsock库中可以使用的最高的版本号;需要注意的是,这些值中高阶字节表示minor版本号,低阶字节表示major版本号。szDescription和szSystemStatus由Winsock的特殊的实现所设置,并不会被真正使用。不要使用iMaxSockets和iMaxUdpDg这两个域,iMaxSockets表示同时打开套接字的最大数量,iMaxUdpDg表示数据报的最大大小。可以通过WSAEnumProtocols()函数来查询数据报的最大大小。同时打开套接字的最大数量不是一个magic number,它依赖于可使用的物理资源。lpVendorInfo为特定的供应商信息,该域不会被任何Windows平台所使用。
3 WSACleanup()函数
当应用程序完成时,需要调用WSACleanup(),该函数允许Winsock来释放所有分配的资源,并且取消所有等待的Winsock调用。
该函数的格式为
int WSACleanup();
如果成功释放了所有资源,则返回值是0;否则返回值是SOCKET_ERROR。
当应用程序退出时,如果调用WSACleanup()失败,则不会有影响,因为操作系统会自动释放这些资源。但是,在调用WSAStartup()之后都要调用WSACleanup()。
4 相关代码
在使用上述代码进行Winsock编程时,需要添加《Winsock网络编程头文件及库文件的设置》中提到的头文件和库文件。
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
在初始化Winsock动态库之后,可以对wsaData中的wVersion成员变量进行判断,用来确认加载的Winsock动态库的版本是否是2.2。
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
WSACleanup();
需要注意的是,即使程序加载的Winsock动态库版本超过2.2,但是由于在WSAStartup()函数中我们已经指定了Winsock动态库所需的版本,此时wVersion中保存仍然是2.2版本。如果Winsock动态库版本低于2.2,则wVersion中保存的是动态库的实际版本号。
最后,程序调用WSACleanup()函数释放网络资源。