在 WinSock 中处理异步套接字?

2023-11-23

我正在使用消息窗口和 WSAAsyncSelect。如何使用一个消息窗口跟踪多个套接字(客户端)?


Windows 支持多种套接字操作模式,您需要明确您正在使用哪一种:

  • 阻塞套接字。发送和接收块。
  • 非阻塞套接字:send和recv返回E_WOULDBLOCK,并且select()用于确定哪些套接字已准备好
  • 异步套接字:WSAAsyncSelect - 套接字将事件通知发布到 HWND。
  • EventSockets:WSAEventSelect - 套接字信号事件。
  • 重叠套接字:WSASend 和 WSARecv 通过传入 OVERLAPPED 结构与套接字一起使用。重叠套接字可以与 IOCompletionPort 结合使用,并提供最佳的可扩展性。

就方便性而言,异步套接字很简单,并且由 MFC CAsyncSocket 类支持。

事件套接字的使用很棘手,因为可传递给 WaitForMultipleObjects 的最大对象数为 64。

具有 IO CompletionPorts 的重叠套接字是处理套接字的最具可扩展性的方式,并允许基于 Windows 的服务器扩展到数万个套接字。


根据我的经验,在使用异步套接字时,我会想到以下几点:

  • 通过窗口消息处理 FD 事件可以处理“大量”套接字,但性能将开始受到影响,因为所有事件处理都是在一个线程中完成,并通过消息队列进行序列化,如果在单线程中使用,消息队列也可能忙于处理 UI 事件图形用户界面应用程序。

  • 如果您在与许多套接字相同的线程上托管 GUI 窗口或计时器:WM_TIMER 和 WM_PAINT 消息的优先级较低,并且仅在消息队列为空时才会生成。因此,非常繁忙的套接字可能会导致 GUI 绘制或基于 SetTimer 的计时失败。

  • 如果托管 GUI 可以解决这些问题,则创建专用工作线程来处理套接字。鉴于工作线程将有一个消息循环,您可以使用消息队列进行线程间通信 - 只需将 WM_APP 消息发布到线程即可。

  • 将 FD 回调映射到套接字对象的最简单方法是为每个将接收消息的 HWND 创建一个 SocketObjects 数组,然后在每次调用 WASAsyncSelect 时使用 WM_USER+index 作为消息 ID。然后,当您收到 WM_USER 到 WM_USER+(数组大小)范围内的消息时,您可以快速提取相应的状态对象。 WM_USER 为 0x400,WM_APP 为 0x8000,因此您可以使用此方法为每个消息窗口最多索引 31744 个套接字。

  • 不要使用静态范围数组。您需要将数组与窗口关联起来,因为您可能希望在多个线程上创建套接字。每个线程都需要自己的消息循环和消息窗口。

  • HWND_MESSAGE 是你的朋友

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 WinSock 中处理异步套接字? 的相关文章

  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐