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

时间:2012-11-01 05:13:33

标签: windows multithreading sockets winsock2

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

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

问题是当工作线程想要发送响应数据时,在工作线程尝试发送其结果时,网络线程可能在poll()内睡着了。网络线程必须等待poll()超时(或另一个要接收的数据包)才会注意到有新的出站数据排队等待发送。

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

感谢您的任何建议!

2 个答案:

答案 0 :(得分:1)

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

1)您已尝试在此连接上发送数据,并且操作系统的发送队列已满。在这种情况下,无需中止selectpoll。无论如何,您现在无法立即写入连接,并且您将尽快自动退出selectpoll

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

你真的不应该在Windows上使用select。这是一种令人厌恶的憎恶,只是作为兼容性的粗暴黑客。如果你计划“真正”支持Windows,你不应该让它成为二等。网络I / O实际上必须是特定于平台的。

答案 1 :(得分:0)

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