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

5
我需要同时进行发送和接收操作。哪种选项更好:
1. 使用非阻塞套接字的1个线程处理发送和接收 2. 使用2个线程,其中一个处理阻塞式接收(recv()),另一个处理发送
还有其他解决方案吗?
我预计会有大约50个双向连接,选项#1将导致50个线程,选项#2将导致100个线程。
4个回答

4

我不会使用这两种方法中的任何一种。

看一下这个SO问题。我会使用工作线程模型,其中你将有N个线程处理所有具有非阻塞套接字的流量。

如果您绝对必须遵循您刚刚描述的方法之一,请选择非阻塞IMHO。


尽管这个问题不是一个Java问题,但它非常适合在Java中使用Executors,它几乎实现了你在链接帖子中描述的模型。 - C. K. Young
是的。执行器很棒。绝对没错。 - Pablo Santa Cruz

3

你应该使用非阻塞的套接字,但是不要手动轮询它们,而是让内核为你完成。使用pollselect来实现(前者更受欢迎,因为它可以同时处理更多的套接字)。这样做后,选项1中将只有1个线程,而选项2中将有2个线程。:-P


poll是标准的C/C++函数吗?我似乎找不到它。 - xcimo
这显然是一个“X/Open系统接口扩展”:http://www.opengroup.org/onlinepubs/009695399/functions/poll.html - C. K. Young
在这种意义上,select 可能是“更标准”的:http://www.opengroup.org/onlinepubs/009695399/functions/select.html(不过,我仍然支持使用 poll,在支持它的平台上。) - C. K. Young

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

这样,您就不需要进行轮询,因为select()会阻塞而不使用处理器时间。


使用轮询(poll)而不是选择(select)! :-P(好吧,如果您正在使用WinSock,则选择可能更便携,但在这种情况下,您也可以使用WSAWaitForMultipleEvents,它类似于 poll。:-P) - C. K. Young
1
这是他问题中“或者还有其他选项吗?”部分的答复。由于他没有提及任何平台,我选择了最具可移植性的版本,即select() [可在C/C++、Windows/Linux、PERL和许多其他语言中使用!] - mmmmmmmm

0

如果您关心性能和可扩展性,请尝试使用IOCP(异步套接字读/写):如何编写可扩展的基于Tcp/Ip的服务器

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

尝试简单的方法并进行测量...但是如果您需要更高的性能或者将要扩展到50个连接之外,认真考虑IOCP作为更好的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接