我同意@DavidHeffernan - UI 线程应该做 UI 的事情。 IO 线程肯定需要绑定和端口(服务器),或对等地址和端口(客户端)。来自 ConnectEx 或 AcceptEx 的套接字肯定会更好地加载到 IO 线程中,但是肯定可以在 UI 线程中创建一个带有(此时未定义)套接字成员的 Socket 类,并将其发送给 IO 线程进行处理。缓冲区是构成 Socket 类的一部分,还是单独的 Buffer 类,是设计考虑因素。
一个实现,(我已经成功使用):
设计/定义“线程间通信”(ITC)消息类。这有一个“命令”枚举成员,可以告诉其他线程做一些事情,以及此类消息中可能需要的任何其他有用的东西
从 ITC 派生一个“Socket”类。这包含 IP/端口、套接字句柄和其他任何可能需要的字符串成员。
从 ITC 派生一个“缓冲区”类。这有一个“BoundSocket”成员、缓冲区空间和一个“OVERLAPPED”结构。
与 IO 线程的通信相当容易。由于它必须等待一些可变的东西,它可以等待一个管理“命令”并发队列的信号量。
如果您的 UI 希望指示 IO 线程连接到服务器,它会创建一个 Socket 实例(新),从 UI 元素加载 IP 和 Port 成员,将 Command 枚举设置为“Connect”,将套接字推送到命令队列并发出信号量 (ReleaseSemaphore)。
IO 线程中的警报等待然后返回 WAIT_OBJECT_0,(它需要忽略返回 WAIT_IO_COMPLETION),因此知道命令已排队。它从命令队列中弹出它并作用于命令枚举(可能打开它),以执行所需的操作。对于连接,这将涉及一个重叠的“ConnectEx”调用来排队连接请求并设置连接完成处理程序。
连接完成处理程序在调用时会检查是否成功连接,如果是,则可以新建一个缓冲区,加载它,发出一个 WSARecv 以供服务器发送内容并将返回的 Socket 对象存储在容器中.如果失败,它可以加载 Socket
带有合适的错误消息并将其 PostMessage 发送回 UI 线程以通知用户失败。
看——没那么难,不需要10000行代码:)
唯一我不知道如何立即做的事情是从完成例程中返回的 OVERLAPPED 结构中获取套接字对象的“this”。在 32 位系统上,我将 Buffer 'this' 推入 Buffer 实例中重叠结构的 hEvent 字段中,并将其转换回完成例程中。 Buffer 实例有一个 Socket 引用,所以工作完成了。在 64 位系统上,hEvent 没有足够的空间来存储 48/64 位“this”缓冲区指针,并且(显然)这需要一个扩展的 OVERLAPPED 结构:( 不确定这是如何完成的 - 也许你会发现:)
[edit] @BenVoigt 对 32/64 位“在完成例程中获取 Socket 上下文 'this'”问题提出了建议 - 这比我想象的要容易:):
https://stackoverflow.com/a/28660537/758133