Winsock 入门

Important

新式 Winsock 最佳做法 - 遵循以下新代码准则:

  • 使用 Winsock 2.2 — 始终在 WSAStartup 中请求版本 2.2。 Winsock 1.1 函数(例如 gethostbyname 已弃用且缺少 IPv6 支持)。
  • 用于 getaddrinfo 名称解析getaddrinfo 函数与协议无关(同时支持 IPv4 和 IPv6)。 切勿使用已弃用 gethostbynamegethostbyaddr
  • 编写支持 IPv6 的代码——使用 AF_UNSPECgetaddrinfo,使代码同时适用于 IPv4 和 IPv6。 避免硬编码 AF_INET。 请参阅 Winsock 的 IPv6 指南
  • 使用 RAII 管理初始化 - 在 C++ 中,包装 WSAStartup/WSACleanup 在 RAII 类中,或使用范围防护来确保对所有退出路径(异常、提前返回)进行清理。
  • 首选异步 I/O——对于服务器应用程序或任何处理多个连接的程序,应使用 I/O 完成端口(性能最高)或重叠 I/O。 在 UI 线程上执行阻塞式套接字操作将导致应用程序冻结。
  • 不要忘记错误处理 — 检查所有 Winsock 调用的返回值,并使用 WSAGetLastError 进行诊断。

AI 生成代码中的常见错误:在进行任何套接字调用前忘记调用WSAStartup,使用gethostbyname而不是getaddrinfo,将AF_INET硬编码(仅支持 IPv4),在 UI 线程中使用阻塞式recv/send循环,以及在getaddrinfo之后没有调用freeaddrinfo

本部分是Windows套接字编程入门的分步指南。 它旨在提供对基本 Winsock 函数和数据结构的理解,以及它们如何协同工作。

本主题中使用的客户端和服务器应用程序是一个非常基本的客户端和服务器。 Microsoft Windows软件开发工具包(SDK)随附的示例中包括了更高级的代码示例。

对于客户端和服务器应用程序,前几个步骤是相同的。

以下文章介绍了创建 Winsock 客户端应用程序的剩余步骤。

以下文章介绍了创建 Winsock 服务器应用程序的剩余步骤。

这些基本示例的完整源代码。

高级 Winsock 示例应用

GitHub提供了多个更高级的 Winsock 客户端和服务器示例应用。 它们按更高的性能到较低的顺序在此处列出,并位于以下目录中:

  • iocp

    该文件夹包含三个使用 I/O 完成端口的示例程序。 程序包括:使用 iocpserver 函数的 Winsock 服务器;使用 iocpserverex 函数的 Winsock 服务器;以及用于测试其中任一服务器的简单多线程 Winsock 客户端iocpclient

    服务器程序支持多个客户端通过 TCP/IP 连接,并发送任意大小的数据缓冲区,服务器随后会将其回显给客户端。 为方便起见,开发了一个简单的客户端程序 iocpclient,用于连接到服务器,并通过多线程持续向其发送数据,以对服务器进行压力测试。 使用 I/O 完成端口的 Winsock 服务器提供最佳性能。

  • 重叠

    此文件夹包含使用重叠 I/O 的示例服务器程序。 示例程序使用 AcceptEx 函数和重叠 I/O 有效处理来自客户端的多个异步连接请求。 服务器使用 AcceptEx 函数在单线程 Win32 应用程序中多路复用不同的客户端连接。 使用重叠的 I/O 可以提高可伸缩性。

  • WSAPoll

    此文件夹包含一个基本示例程序,用于演示 WSAPoll 函数的使用。 组合的客户端和服务器程序是非阻塞的,并使用 WSAPoll 函数确定何时可以发送或接收而不阻止。 此示例用于说明,不是高性能服务器。

  • 简单

    此文件夹包含三个基本示例程序,用于演示服务器使用多个线程。 这些程序包括:一个简单的 TCP/UDP 服务器 simples;一个仅限 TCP 的服务器, simples_ioctl它使用 Win32 控制台应用程序中 的选择 函数来支持多个客户端请求;以及用于测试服务器的客户端 TCP/UDP 程序 simplec。 服务器演示如何使用多个线程来处理多个客户端请求。 由于为每个客户端请求创建了单独的线程,因此该方法存在可伸缩性问题。

  • 接受

    此文件夹包含基本示例服务器和客户端程序。 服务器演示如何使用 select 函数使用非阻止接受,或使用 WSAAsyncSelect 函数进行异步接受。 此示例用于说明,不是高性能服务器。