【问题标题】:Porting multithreaded network server from unix to windows将多线程网络服务器从 unix 移植到 windows
【发布时间】:2012-11-01 05:13:33
【问题描述】:

我正在努力将一些相对简单的网络代码从 unix 移植到 Windows。

简而言之,有一个管理所有网络流量的网络线程。这个单线程大部分时间都位于poll() 中(我已经将它转换为select(),在Windows 上),网络线程只有在有传入的网络数据时才会唤醒。当客户端命令到达时,网络线程将命令触发到工作线程以实际在后端执行工作,然后返回侦听更多传入命令。命令是异步的——多个命令可以在一个套接字上输入,一个接一个接一个。在任何时候,单个连接上可能有几十个未完成的命令,所有命令都在不同的工作线程中处理。

问题在于,当工作线程想要发送响应数据时,网络线程可能在工作线程试图发送其结果时在poll() 内处于休眠状态。网络线程必须等待poll() 超时(或接收到另一个数据包),然后才会注意到有新的出站数据排队等待发送。

在 unix 下,我通过在poll() 监视的描述符中包含一个管道来处理这个问题,当工作线程有出站数据要发送时,它还会将一个字节的数据写入管道以唤醒网络线。但是 WinSock 似乎只支持等待套接字,所以这种方法在 Windows 中对我不起作用。有什么方法可以让我在 Windows 上使用 WinSock 来挽救这个架构(这样我就可以在不同平台之间共享大部分代码),或者除了编写一个用于 Windows 的自定义网络服务器实现之外别无选择?

感谢您的建议!

【问题讨论】:

    标签: windows multithreading sockets winsock2


    【解决方案1】:

    只有两种可能性,并且都不需要您提出的解决方案:

    1) 您已经尝试在此连接上发送数据并且操作系统的发送队列已满。在这种情况下,无需退出selectpoll。反正你现在不能在连接上写,你会尽快自动退出selectpoll

    2) 您当前没有尝试在此连接上发送数据。在这种情况下,也无需退出selectpoll。现在只需在工作线程中写入数据。 (socket是非阻塞的吧select 打电话)。

    你真的不应该在 Windows 上使用select。这是一个可憎的行为,仅作为兼容性的粗略黑客提供。如果您计划“真正”支持 Windows,则不应将其设为二等舱。网络 I/O 确实必须是特定于平台的。

    【讨论】:

      【解决方案2】:

      与在 Windows 上使用 select 不同,如果您使用 IO 完成端口和发布的读取缓冲区,您将获得明显更好的结果。在 IOCP 模型下,可以使用PostQueuedCompletionStatus API 与为 IOCP 提供服务的线程进行通信。

      【讨论】:

      • 是的,绝对正确。但在这种情况下,我正在使用为 BSD 套接字编写的现有代码,并且我正在尝试最小化我必须为 Windows 构建编写和维护的自定义代码的数量。如果在这段代码中性能确实成为问题并且分析点,那么切换到 IOCP 是我列表中的第一件事。在那之前,我可能不会打扰。 :)
      最近更新 更多