子进程之间共享的侦听器套接字是否需要互斥锁?

时间:2016-02-02 19:17:10

标签: multithreading sockets network-programming

我正在使用C ++开发服务器应用程序。我设计的方式是主要进程,负责维护子进程( worker )。工人accept()新连接并创建线程以便单独处理它们。

假设我在进程中创建一个侦听器套接字,并且每个 worker 将监视它(使用kqueue,epoll等)以进行新连接。经过一番研究后,我发现了一些肯定,即需要在侦听器套接字上使用mutex来防止并发accept(),这会导致工作人员accept()同时连接相同的连接。

嗯,意识到这种需求,我不确定在工作人员之间分配客户连接的最佳方式是什么,因为结果与accept()相同他们在进程中以某种方式将新套接字FD发送给工作人员(新连接处理变为阻塞 - 一次只有一个accept()

我的问题是:真的需要在侦听套接字上mutex吗?我对accept()阻止(一次一个新连接accept())副作用是对吗?

我担心这个单一的细节,因为这个应用程序必须每秒扩展到数千个新连接(具体数量可能会有所不同,因为此应用程序旨在用于具有100到1000个客户端的网络)。

2 个答案:

答案 0 :(得分:3)

很久以前,如果多个进程在同一个套接字上同时执行accept,那么操作系统会遇到竞争条件。 Apache曾经有一个可选的接受互斥来解决这个问题。

此问题早已在您可能使用的每个操作系统上得到解决,并且使用工作人员呼叫accept的共享套接字是完全合理的。如果您希望每个工作程序一次只处理一个连接,则空闲工作程序可以在共享套接字上阻塞accept

  

我担心这个单一细节,因为这个应用程序必须每秒扩展到数十万甚至数百万个新连接。我想避免编写两个复杂应用程序的工作,其唯一目的是比较两种方法的性能。此外,我无法模拟真实世界的同步连接。

你不能双管齐下。要么你放弃这样雄心勃勃的扩展计划,要么你接受你将有许多重大的努力。只是模拟这种连接负载进行测试将是一项重大工作。

答案 1 :(得分:-2)

我无法回答关于listen()和accept()调用的线程安全问题的部分问题,因为我甚至都不会考虑尝试。我要做的是让主线程执行listen()和accept(),并在accept()返回时分叉一个新线程,将套接字传递给线程。
类似地,您可以拥有一堆正在运行的线程,并且互斥一个将执行套接字通知的变量。基本上与上面相同,但不是在接受时创建线程,而是通知已经运行的套接字描述符线程。一般伪代码可能是:

main()
{
  listen();
  while(true)
  {
    int socket = accept();
    if(fork() == 0)
    {
       DoMyThing(socket);
    }
  }
}