基本级别的事件循环类似于:
while getNextEvent (&event) {
dispatchEvent (&event);
}
换句话说,它只不过是一个循环,它不断地从某个描述的队列中检索事件,然后将事件分派到事件处理过程。
您可能已经知道这一点,但我只是根据上下文进行解释。
就不同服务器如何处理它而言,似乎在 Apache 中建立的每个新连接都有一个为其创建的线程,并且该线程负责该连接而不是其他任何事情。
对于另外两个,可能有“固定”数量的线程正在运行(尽管这实际上可能因负载而异),并且连接被移交给其中一个线程。这意味着任何一个线程都可能在任何时间点处理多个连接。
因此,在这种情况下,事件必须包含一些关于它适用于什么连接的详细信息,以便线程可以保持不同的连接彼此隔离。
毫无疑问,这两种选择都有利弊。每个线程一个连接选项将简化线程函数中的代码,因为它不必处理多个连接,但随着负载变高,最终可能会占用大量资源。
在每个线程多连接的情况下,代码稍微复杂一些,但您通常可以通过始终运行最大数量的线程来最小化线程创建和销毁开销。在高负载时段之外,他们只会坐在那里无所事事,等待给他们的连接事件。
而且,即使在高负载下,每个线程也可能很容易地处理五个并发连接而不会落后,这意味着每个线程一个连接的选项有点浪费。
根据您的更新:
我的意思是如果在 1 个线程下与 3 个套接字进行通信,那么 1 个线程如何在不让任何人等待的情况下与 3 个套接字进行通信?
有很多方法可以做到这一点。首先,它通常会在getNextEvent()
调用之后被抽象出来,这可能会负责处理所有连接并将它们分配给正确的线程。
在最低级别,这可以通过诸如select
调用之类的方法来完成,该函数等待许多文件描述符之一上的活动,并返回与哪个文件描述符有话要说相关的信息。
例如,您提供所有当前打开的套接字的文件描述符集并将其传递给select
. 然后它会给你一个修改后的集合,只包含你感兴趣的那些(例如ready-to-read-from)。
然后,您可以查询该集合并将事件分派到相应的线程。