避免在多线程套接字应用程序中重用相同的fd编号

时间:2009-10-01 14:32:02

标签: c++ linux multithreading sockets

我有一个异步应用程序执行多个线程,这些线程通过套接字执行操作,在这些线程上调度操作然后异步执行。

我试图避免在第一次操作开始执行之前,一旦在套接字上调度读取操作,套接字被关闭并重新打开(可能是另一个操作中的另一个对等体)的情况,这将最终读取适当的文件描述符,但错误的对等。

问题来了,因为(accept(); close(); accept())在accept()中返回相同的fd,这可能导致上述情况。

我看不到避免它的方法。

任何提示?

6 个答案:

答案 0 :(得分:3)

好的,找到了答案。

这里最好的方法是调用accept()并获得最低的fd,用你已知的数字复制它,如dup2(6,1000)和close(6),你现在可以控制你的fd范围了使用

接下来将接受6或类似的再次接受,我们将重复2(6,999);并且继续这样下降,如果它变得太低则重新设置它。

由于接受总是在同一个线程中完成而且dup2和close相比,并不总是在那里完成接受,因此它非常适合我的需要。

答案 1 :(得分:2)

你如何管理套接字?听起来你有多个线程可以:

  1. accept传入连接
  2. close现有连接
  3. 建立新的外向连接
  4. 听起来你需要一种方法来调解对浮动的各种插座的访问。您是否考虑将每个套接字与互斥锁相关联,以防止在仍在使用时关闭套接字,或者可能将每个套接字描述符放在具有原子引用计数的结构中,这将阻止其他线程关闭它,直到所有线程都使用它完成为止?

答案 2 :(得分:1)

套接字是一个5元组{local-addr,local-port,remote-addr,remote-port,proto},所以如果你能够使用这些属性代替fd进行事件/处理程序路由,你可以避免fd冲突。

另一种选择是序列化所有close()/ accept()操作(优先级?),以便它们不能混合

答案 3 :(得分:1)

好问题!我甚至没有意识到会出现这样的问题。

我能想到的唯一答案是你不使用close()来表示套接字被终止。一种解决方案是使用shutdown()来终止连接。然后,您可以通过引用计数安全地关闭()套接字。

答案 4 :(得分:1)

我仍然会小心将dup2()用于众所周知的fd值。请记住,dup2()会在重复之前在目标上执行关闭;如果你开始打开1000个文件,这可能会与一些不相关的I / O无关的线程发生冲突。

如果我是你,考虑到你所坚持的限制,我会在互斥锁中使用dup()(而不是dup2())。 (如果你担心它,可能是per-fd互斥体。)

答案 5 :(得分:0)

保持每个套接字的挂起操作(读/写等)的计数,以及套接字上是否有挂起的关闭请求。在您关闭之前,先检查是否有任何待处理的操作。如果有,则调用shutdown,然后仅在挂起的操作计数达到0时调用close。