非阻塞套接字轮询与阻塞套接字

Posted

技术标签:

【中文标题】非阻塞套接字轮询与阻塞套接字【英文标题】:Non-blocking Socket Polling vs Blocking socket 【发布时间】:2010-10-31 07:58:12 【问题描述】:

我需要同时发送recv。 哪个选项更好:

1 个线程使用非阻塞套接字处理发送和接收

2个线程,1个处理阻塞recv() + 1个处理send()?

或者有其他解决方案吗?

我预计最多有 50 个双向连接。这导致选项 #1 中有 50 个线程,选项 #2 中有 100 个线程。

【问题讨论】:

【参考方案1】:

你可以使用一个线程和两个非阻塞套接字,并使用 select() 来等待传入的输入和输出队列中的空间。

那么你不需要轮询,因为 select() 阻塞而不使用处理器时间。

【讨论】:

投票,不选择! :-P(好吧,如果你使用 WinSock,select 可能更便携,但在这种情况下你也可以使用 WSAWaitForMultipleEvents,就像 poll。:-P) 这是对“或者还有其他选择吗?”的回答。他的问题的一部分。由于他没有提到任何平台,我选择了最便携的版本,即 select() [可用于 C/C++、Windows/Linux、PERL 和许多其他语言!)【参考方案2】:

您应该使用非阻塞套接字,而不是手动轮询它们,您应该让内核为您完成。为此使用pollselect(前者是首选,因为它可以一次处理更多套接字)。当你这样做时,你最终会在选项 1 中得到 1 个线程,或者在选项 2 中得到 2 个线程。:-P

【讨论】:

是轮询标准 C/C++ 函数吗?好像没找到。。谢谢 这显然是一个“X/开放系统接口扩展”:opengroup.org/onlinepubs/009695399/functions/poll.html 从这个意义上说,select 可能是“更标准的”:opengroup.org/onlinepubs/009695399/functions/select.html(但是,对于支持它的平台,我仍然支持使用 poll。)【参考方案3】:

我不会使用这两种方法。

看看this SO 问题。我会使用一个工作线程模型,在该模型中,您将有 N 个线程使用非阻塞套接字处理所有流量。

如果您绝对必须遵循您刚才描述的方法之一,请使用非阻塞恕我直言。

【讨论】:

+1 虽然这个问题不是 Java 问题,但它非常非常适合在 Java 中使用 Executors,它几乎实现了您在链接帖子中描述的模型。跨度> 是的。执行者很棒。绝对。【参考方案4】:

如果您担心性能和可扩展性,请尝试 IOCP(异步套接字读/写):How to write a scalable Tcp/Ip based server

请注意,实现 IOCP 比“每个连接一个线程”要复杂得多,而且由于您将只有 50 个连接(或您建议的 100 个线程),这可能“足够好”并且更简单正确实施。

尝试简单的方法并对其进行测量...但如果您:需要更高的性能,或者要扩展(远?)超过 50 个连接,请认真考虑 IOCP 作为更好的解决方案。

【讨论】:

以上是关于非阻塞套接字轮询与阻塞套接字的主要内容,如果未能解决你的问题,请参考以下文章

Linux 中的异步套接字——轮询与回调通过

python IO模型

从阻塞套接字更改为非阻塞套接字有啥好处?

什么可能导致非阻塞套接字阻塞“recv”?

11 非阻塞套接字与IO多路复用(进阶)

非阻塞套接字仍然可以在 OpenSSL 中阻塞吗?