跳到内容

Windows 编程/Winsock

来自维基教科书,开放书籍,共建世界

Winsock 是 Windows 中处理 Berkely Socket API 的库的名称。从技术上讲,这个库不是 Win32 API 的一部分,尽管在编写 Winsock 应用程序时需要考虑一些 Windows 特定的问题。

创建 Winsock 项目

[编辑 | 编辑源代码]

可以通过包含 <winsock2.h> 头文件将 Winsock 添加到您的编程项目中。此头文件用于库的 32 位版本。对于 16 位版本,包含文件 <winsock.h>。

winsock.dll 是库的 16 位版本,ws2_32.dll 是 32 位版本。您必须指示链接器链接到库的适当版本。

初始化 Winsock

[编辑 | 编辑源代码]

在调用任何 Winsock 例程之前,必须首先通过调用 WSAStartup 函数来初始化库。此函数需要指向 WSADATA 结构的指针。您不需要初始化此结构,因为对 WSAStartup 的调用将填充结构的所有字段。您可以选择从该结构中读取值,并在您的程序中使用结果。然而,这不是必需的。WSAStartup 还要求您指定要使用的 Winsock 版本。Winsock 的最新版本是 1.1 版,尽管库的最新版本是 2.0 版。要指定此参数,请将主版本和次版本传递给 MAKEWORD 宏。以下是一个示例

WSADATA wd;
WSAStartup(MAKEWORD(2, 0), &wd);

以下是 WSADATA 结构的定义。从这个数据结构,您可以确定一些重要的系统指标,包括您的库的版本,可用的最大并发套接字数量等。

typedef struct WSAData {
 WORD wVersion;
 WORD wHighVersion;
 char szDescription[WSADESCRIPTION_LEN+1];
 char szSystemStatus[WSASYS_STATUS_LEN+1];
 unsigned short iMaxSockets;
 unsigned short iMaxUdpDg;
 char FAR* lpVendorInfo;
} WSADATA, *LPWSADATA; 

WSAStartup 的定义如下

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

此函数在成功时返回零,并在失败时返回非零。这些错误代码可以被处理,或者程序可以中止。

退出 Winsock

[编辑 | 编辑源代码]

程序完成后,它必须调用 WSACleanup,以从列表中注销自己,并释放库使用的任何资源。WSACleanup 不接受任何参数,并在成功时返回零。非零返回值表示清理过程中发生错误。

套接字作为句柄

[编辑 | 编辑源代码]

有人说,与 UNIX 不同,Win32 不允许使用文件 I/O 函数读取/写入套接字。这只有一半是对的。套接字不能使用标准库函数(如 fread、fwrite、fprintf 等)访问。但是,如果我们将 SOCKET 结构转换为 HANDLE 结构,我们就可以使用 Win32 文件 I/O API 来与套接字交互。例如,我们现在可以使用 ReadFile 和 WriteFile 来写入套接字,并且我们在这些 API 周围编写的任何例程都可以用于写入网络。

在 Win32 下,不要尝试将 SOCKET 转换为 FILE 类型,并使用 stdio.h 文件函数。这将导致某种错误(最可能是错误错误)。

高级 Win32 套接字

[编辑 | 编辑源代码]

Win32 拥有完整的套接字函数,包括 bind、accept、socket、listen 和 recv。但是,Win32 还提供了一些高级函数变体,这些变体允许使用高级操作模式。例如,使用高级套接字函数允许重叠 I/O 模式、异步模式、事件等。这些函数可以在 MSDN 上查看。

华夏公益教科书