[杂烩]Windows IOCP与Linux的epoll机制对比

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[杂烩]Windows IOCP与Linux的epoll机制对比相关的知识,希望对你有一定的参考价值。

参考技术A 看到一些资料,说Windows的IOCP后发制人,比Linux的epoll优越很多。那么优势到底在哪里?如何选择Linux或Windows作为服务器呢?
也看到有资料说,同样在Linux上,使用reactor机制的网络库性能比使用Proactor机制的Asio性能好接近1/5,这个例子可能与题目无关,不过我在文中可能会做一些相关的分析。

系统I/O模型 可分为三类:

IOCP基于非阻塞异步模型,而epoll基于非阻塞同步模型。

参考 Hyunjik Bae, A game programmer since 1995 说的:

参考[4]比较了Windows IOCP和Linux epoll的性能,结论是如果使用Linux,应该使用支持RSS(multi-queue)的NIC,这样可以达到与IOCP类似的性能。

Boost.Asio为了兼容Windows和Linux,在Linux上用epoll和select去模拟proactor模式,影响了它的效率和实现复杂度。其效率不及使用原生I/O机制的其它实现为Reactor模式的网络库。

引用来自参考[3]的话:

[1] Why doesn't Linux have a system like IOCP or Rio does? , 2014.
[2] 两种高性能I/O设计模式(Reactor/Proactor)的比较 - 文章 - 伯乐在线
[3] Practical difference between epoll and Windows IO Completion Ports (IOCP)
[4] Windows IOCP vs Linux EPOLL Performance Comparison

将 IOCP 与 send() 和 recv() 一起使用

【中文标题】将 IOCP 与 send() 和 recv() 一起使用【英文标题】:Using IOCP with send() and recv() 【发布时间】:2016-02-05 21:43:38 【问题描述】:

我正在尝试找出处理与我的 C++ TCP 服务器的多个连接的最佳方法。我偶然发现了epoll(),但遗憾的是它只适用于 Linux,我在 Windows 上做所有事情。

经过一些研究,在 Windows 上处理套接字的最佳方法似乎是使用 I/O 完成端口。我想使用它们,但是客户端应用程序使用send()recv()(我无法更改),这意味着我还需要使用相同的函数来发送和接收来自客户端的数据。这些函数似乎没有用于 IOCP(使用WSASend() / WSARecv() 代替)。

我想知道是否还有任何方法可以将 IOCP 与 send()recv() 一起使用?还是我应该看看其他方法?

【问题讨论】:

检查选择功能msdn.microsoft.com/en-us/library/windows/desktop/… 我确实检查了它,我读过它在很多套接字上都做得不好,这是我主要关心的性能。 【参考方案1】:

我还需要使用相同的函数向客户端发送和接收数据

这是不正确的。客户端不知道您如何将数据传入和传出 TCP 连接,无论是通过网络发送相同的确切 TCP 段的方式。

如果您的服务器受 I/O 限制,那么 WSAAsyncSelect 和/或 WSAEventSelect 工作得很好(并为您省去了多线程的麻烦)。 IOCP 仅适用于计算密集型服务,因为它们将工作项分配到可用线程,因此并发请求可以启动并在多个处理器内核上进行计算。

WSAPoll 是另一种选择。

【讨论】:

我读到了 WSAPoll,它似乎是 Windows 的 epoll() 等价物,但它似乎有问题,微软不会修复它。 @Spook:我刚刚再次阅读了该投诉,是的,它的行为与 Linux poll 完全不同,尤其是在连接尝试失败方面。但是,合同是“遵循文档”而不是“与不同操作系统上具有不同名称的函数的确切行为相匹配”,并且看起来它的行为确实与记录的一样。所以你可以称之为一个不幸的设计决定,但不是一个错误。无论如何,如果它困扰您,请使用我提到的其他三种方法中的任何一种。 好的,谢谢您的回复!过去我曾尝试使用带有 HWND 的 WSAAsyncSelect 来接收通知,它确实工作得很好,我只是认为 IOCP 会是一个更好的选择。另外,您是说可以使用 send() 并使用 WSARecv() 接收吗?这对我来说似乎不太可能,但我宁愿在编写实现它的代码之前在这里问一下。 “你是说可以使用 send() 并使用 WSARecv() 接收吗?” 绝对有可能。您是否停下来想过您所期望的意味着使用 IOCP 构建的每个 Web 服务器只能由也使用 IOCP 的 Windows Web 浏览器使用?那将使 IOCP 完全无用。幸运的是,有一些网络标准允许不同的操作系统和不同的 API 相互通信,只要它们都符合 TCP RFC。 嗯,这对我来说似乎不太可能,但这是个好消息,因为这将允许我在使用 WSASend() / WSARecv() 时使用 IOCP,即使客户端使用 send() 和接收()。 “您是否停下来认为您所期望的意味着使用 IOCP 构建的每个 Web 服务器只能由也使用 IOCP 的 Windows Web 浏览器使用” 不是真的,但我挑战你找到任何现有的使用 send 的文章/代码() 在客户端,并在使用 IOCP 时在服务器端使用 WSARecv() 接收。非常感谢您解决这个问题!

以上是关于[杂烩]Windows IOCP与Linux的epoll机制对比的主要内容,如果未能解决你的问题,请参考以下文章

Windows完成端口 IOCP模型

DIOCP DIOCP常见问题。

Nginx源码分析 - Nginx启动以及IOCP模型

Win32:不可能将 iocp 与标准输入句柄一起使用

Windows下用CMake编译 libuv

网络模型之IOCP与扩展函数