Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带Select的非阻塞套接字_C_Networking_Nonblocking - Fatal编程技术网

带Select的非阻塞套接字

带Select的非阻塞套接字,c,networking,nonblocking,C,Networking,Nonblocking,我不理解在非阻塞套接字上调用recv()与在select返回recv()已准备好读取后等待调用recv()后调用阻塞套接字之间的区别。在我看来,阻塞套接字无论如何都不会在这种情况下阻塞。 另外,我听说使用非阻塞套接字的一种模式是在经过一段时间后尝试对它们进行调用(recv/send/etc),而不是使用select之类的方法。与使用select之类的工具相比,这种技术似乎既慢又浪费(但是我完全没有达到上述的非阻塞目的)。这在当今的网络编程中很常见吗?选择、轮询、epoll、kqueue等功能针对

我不理解在非阻塞套接字上调用recv()与在select返回recv()已准备好读取后等待调用recv()后调用阻塞套接字之间的区别。在我看来,阻塞套接字无论如何都不会在这种情况下阻塞。

另外,我听说使用非阻塞套接字的一种模式是在经过一段时间后尝试对它们进行调用(recv/send/etc),而不是使用select之类的方法。与使用select之类的工具相比,这种技术似乎既慢又浪费(但是我完全没有达到上述的非阻塞目的)。这在当今的网络编程中很常见吗?

选择、
轮询
epoll
kqueue
等功能针对多个套接字/文件描述符处理场景。想象一下,一台负载沉重的web服务器上同时连接了数百个套接字。如果在非阻塞套接字上调用
read
,如果自上次调用
read
以来没有收到任何数据,它将立即返回。如果您只有
读取
,并且希望等到有数据可用时,您就必须这样做。这会浪费CPU

poll
select
(和朋友)允许您睡眠,直到有数据要读取(或写入,或接收到信号等)


如果您正在做的唯一一件事就是在该套接字上发送和接收,那么您最好使用一个非阻塞套接字。当您同时有其他事情要做时,异步是很重要的,例如更新GUI或处理其他套接字。

对于您的第一个问题,这种情况没有区别。唯一的区别是当没有什么可读时他们会做什么。因为您在调用recv()之前检查了这一点,所以不会看到任何区别


对于第二个问题,我认为在所有库中都可以使用select、poll、epoll、kqueue来测试数据是否可用。从性能角度来看,select方法是最古老的,也是最不可取的(尤其是在管理大量连接时)。

这里有一个关于执行大容量I/O的所有不同选项的概述。至少在2006年,它对许多不同的选择进行了相当全面的调查

从中引用,在非阻塞套接字上使用
的主题中选择

注意:特别重要的是要记住,来自内核的准备就绪通知只是一个提示;当您尝试读取文件描述符时,它可能不再准备就绪。这就是为什么在使用就绪通知时使用非阻塞模式很重要的原因


是的,您可以使用非阻塞套接字,然后让循环在没有准备好的情况下等待,但与使用类似于
select
或更现代的替换方法(epoll,
kqueue
等)相比,这是相当浪费的。我想不出为什么有人真的想这么做;所有的
select
like选项都可以设置超时,因此您可以在一定时间后被唤醒,以执行一些常规操作。我想,如果你在做一些相当CPU密集的事情,比如运行一个视频游戏,你可能想永远不睡觉,而是继续计算,同时使用非阻塞套接字定期检查I/O。

当需要低延迟时,这种繁忙循环相当常见,浪费周期被一些$$(读-金融行业:)。基本上,我们的想法是,不要让内核在系统调用中休眠,这样至少会有两个上下文切换。因此,您可能会这样做有一些原因,但对于大多数应用程序,您通常希望使用类似
select
的循环。
select
可能表示套接字是可读的,但当您读取它时,它就没有可用的数据了。这在很大程度上是一种边缘情况,但在接收到校验和不正确的数据包(只有当应用程序读取数据时才会进行检查)等情况下可能会发生这种情况。