【问题标题】:Calling socket->native_handle() from another thread从另一个线程调用 socket->native_handle()
【发布时间】:2015-10-15 11:13:57
【问题描述】:

我正在编写一些 asio/tcp 服务器,并希望将本机套接字描述符映射到 tcp 会话标识符。 我正在写 id getter 之类的:

inline int get_session_id() { return socket_.native_handle(); }

并从第二个(数据包调度线程)线程调用:

cout << session_shared_ptr->get_session_id() << endl;

并且它只在第一次写入有效 id,所以我猜我的实现中的某些东西是不好的。

谁能告诉我我哪里做错了?

【问题讨论】:

  • 当您说“第一次”时,我假设您在执行输出语句的时间之间做了一些事情?如果您执行两个相邻的输出语句,它是否工作良好?代码中的第一个和第二个输出之间会发生什么?两个输出之间的连接会发生什么?
  • 服务器收到两条消息,传递pair到队列和第二个线程唤醒和解析消息;消息解析没问题,session ptr 也有效,但 session id 无效

标签: c++ linux sockets posix boost-asio


【解决方案1】:

首先,使用本机句柄作为会话 ID 让我觉得这是一个非常糟糕的主意。

您不仅选择了实现定义的后门,还选择了一个不可移植的后门 - 因此您的代码可能会在平台之间获得不同的语义。

请记住,这些是抽象的底层句柄。抽象的存在是有原因的!谁知道,如果您的网络重新连接,本机句柄可能会改变。没有任何地方记录您可以保留句柄并依靠它来识别 API 对象。


当然,当你做多线程时,你必须记住你在线程时总是做的一切:

  • 同步访问共享状态和资源
  • 协调此类对象的生命周期
  • 在执行上述操作时防止饥饿和死锁/软锁

现在,你不谈论同步措施,所以你有一个数据竞赛:

Thread Safety

不同的对象:安全。
共享对象:不安全

标准将数据竞争指定为Undefined Behaviour;任何事情都有可能发生。你可以庆幸你的房子没有被烧毁。然而。


总而言之:只需使用可靠的 ID。生成一个 UUID 并将其存储在会话中。如果你知道你不移动相等的会话,请使用 C++ 对象标识(即 地址)进行标识。

如果您出于某些有用的原因必须从另一个线程访问套接字,请提供同步(互斥 - 互斥,或通过发布到会话链的方式)。

【讨论】:

    猜你喜欢
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多