提问者:小点点

将多线程网络服务器从unix移植到windows


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

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

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

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

谢谢你的建议!


共2个答案

匿名用户

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

1)您已经尝试在此连接上发送数据,并且操作系统的发送队列已满。在这种情况下,无需中止< code >选择或< code >轮询。无论如何,您现在不能在连接上写入,您将尽快自动退出< code>select或< code>poll。

2) 您当前未尝试在此连接上发送数据。在这种情况下,也无需中止选择轮询。只需将数据立即写入工作线程即可。(套接字是非阻塞的,对吧?如果您没有写入所有数据,那只是因为操作系统的发送队列已满,在这种情况下,通常不会急于写入(在选择调用上设置合理的超时)。

不过,您确实不应该在Windows上使用select。这是一种令人厌恶的行为,只是为了兼容性而提供的一种粗暴的攻击。如果你计划“真正”支持Windows,你不应该把它列为第二类。网络I/O实际上必须是特定于平台的。

匿名用户

如果您使用IO完成端口和post读取缓冲区,而不是在Windows上使用< code>select,您会获得明显更好的结果。在IOCP模型下,可以使用< code > PostQueuedCompletionStatus API与服务于IOCP的线程进行通信。