亲爱的朋友们,
我目前正在开发一个网络服务器应用程序。我计划为每个服务器核心分配一个线程来处理客户端连接,以更好地利用服务器资源、获得更快的响应时间并避免阻塞等问题。
据我所知,有两种方法可以实现:
1)父进程打开监听套接字,每个线程监视它(使用epoll、kqueue等)以获取新的连接,并 accept()
它们;
2)每个线程在相同的端口和地址上打开自己的监听套接字(由于 SO_REUSEPORT 和 SO_REUSEADDR 的存在),监视它以获取新的连接并 accept()
它们。
我不确定它背后的工作原理,但我认为像 #2 这样做将把客户端连接分配到各个线程中去,由内核网络部分完成这项任务。这是正确的吗?
这两种方法之间是否有任何显著的区别?在一种方法中可能会出现问题而在另一种方法中却不会出现吗?采用某种特定的方法是否会获得更好的结果(更少的资源使用、更少的延迟等)?
我认为只有通过比较才能看出两种方法之间的差异,但是我的电脑无法处理大量的连接。因此,我倚靠您的经验和知识来回答这个问题。提前感谢您的帮助。
accept()
;但只有一个线程会得到-1和errno == EAGAIN
。SO_REUSEPORT用于多播,而SO_REUSEADDR仅适用于TCP的一种情况,这不是它的用途。 - user207421accept()
被通知新连接。然而,我不确定它是否已经被实现,因此不会依赖它,即使我打算让我的应用程序在FreeBSD上运行。 - Tiago.SRselect()
或poll()
,这意味着非阻塞模式。 - user207421>= 3.9
上,SO_REUSEPORT
确实允许多个线程在同一 IP 和端口上进行监听,即使是 TCP 也是如此。实际上,这就是它被引入的原因。 - Jon Gjengset