gpt4 book ai didi

c++ - 套接字调用在同时执行的两个或多个线程上提供重复的文件描述符(竞争条件)

转载 作者:行者123 更新时间:2023-11-30 02:35:19 30 4
gpt4 key购买 nike

我已经看了,但我还没有看到这个答案。我有一个多线程 C++ 网络服务器类型的应用程序。有多个线程将网络类用于使用不同和特定端口号的不同任务。客户端可以并且确实会根据用户的需要在不同的时间连接/断开连接。当客户端连接时,网络线程基本上同时连接。发生的情况是,有时两个线程会进行 socket() 调用,并且都获得相同的文件描述符。然后 bind() 调用失败,ADDRESS ALREADY IN USE...感谢您没有给我一个未使用的地址套接字调用,大声笑。

需要说明的是,这不是 TIME_WAIT 问题,因此 SO_REUSEADDR 在这里不起作用。旧套接字已成功关闭。这是连接上的竞争条件,其中两个线程使用相同的网络类并从 socket() 调用获取相同的文件描述符。

到目前为止,我唯一发现的是从 C++ 中调用 netstat 来搜索未使用的套接字地址。这似乎仍然存在时间竞争条件。我有五个以上的网络线程都打开套接字。这不是我的设计,而且由于风险管理,我也不能在游戏后期更改它。另外,我要求连接是 100%,而不是 99%。

除了 netstat 和 searching 之类的外部程序,还有其他方法可以解决这个问题吗?如果我必须使用 netstat,有没有人有使用这种方法的可靠代码?

感谢您的宝贵时间,谢谢。

EDIT1:操作系统是 Linux。我假设你是对的,socket API 是线程安全的,谢谢。我更清楚的是,只有当所有线程都被告知由对等方重置时,才会发生这种情况。所以线程都关闭并重新启动彼此靠近的套接字。我 100% 确定文件描述符与我在调试中随处可见的日志相同,并为我提供了足够多的变量值。对于错误情况,文件描述符为 10,但 10 用于另一个已关闭其套接字 fd 的线程。所以我在启动阶段说是两个线程是错误的。一个关闭并释放 10 的 fd,另一个正在启动并获得 10 的 fd。然后,绑定(bind)在此启动线程上失败。由于规则,我不能发布代码,抱歉。

EDIT2:在 socket() 调用和 bind() 调用之间,我确实使用了带有 SO_LINGER 的 setsockopt 并打开了 0 秒。

最佳答案

你有一个错误,你关闭同一个套接字两次。事件的顺序是这样的:

  1. 您的代码正在使用某个套接字,比如 10。

  2. 您获得对等方重置的连接并关闭套接字 10。

  3. 一些线程调用socket,它得到socket 10。

  4. 一些其他线程仍然认为它正在使用原始套接字也发现连接已死并关闭套接字 10 而没有意识到步骤 2 中发生了什么。(例如,它可能调用 send并收到错误,因为新套接字 10 未连接。因此它通过关闭新套接字 10 来“处理”错误。糟糕。)

  5. 一些其他线程调用socket,它得到socket 10。

  6. 您注意到在第 3 步和第 5 步中您得到了相同的套接字。

您可以通过向所有关闭套接字的调用添加日志记录来证明这是问题所在。两次 socket 调用之间将关闭。

解决方案是确保代码中的某些逻辑实体始终拥有您正在使用的套接字,并且只有该实体在套接字上调用close。如果没有该拥有实体的协调,任何其他代码都无法对该套接字执行任何操作。

例如,如果您将发送和接收代码分开,则需要确保除非另一部分已完全关闭,否则这两部分都不能在套接字上调用 close

关于c++ - 套接字调用在同时执行的两个或多个线程上提供重复的文件描述符(竞争条件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33759712/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com