首页 文章

提升ASIO,SSL:股如何帮助实施?

提问于
浏览
4

TLDR:Strands序列化资源在完成处理程序之间共享:如何阻止ssl :: stream实现并发访问SSL上下文(内部使用)以实现并发读/写请求(stream :: ssl不是全双工)?请记住,strand只序列化完成处理程序调用或读/写请求的原始队列 . [感谢sehe帮助我表达更好]


我花了大约一天的时间阅读有关ASIO,SSL和股票的信息;主要是在stackoverflow(有一些非常详细和很好表达的解释,例如Why do I need strand per connection when using boost::asio?)和Boost文档;但有一点仍不清楚 .

显然,绞线可以在同一条链内串行调用回调,因此也可以序列化对这些绞线共享的资源的访问 .

但在我看来,boost :: asio :: ssl :: stream的问题不在完成处理程序回调中,因为它不是在SSL上下文中并发运行的回调,而是ssl :: stream实现 .

我无法确信在调用async_read_some和async_write_some时使用strands,或者使用strands作为完成处理程序,将阻止io引擎在不同的线程中同时在SSL上下文中运行 .

显然,在调用async_read_some或async_write_some时使用链将意味着读取和写入不能在同一时刻排队,但我不知道这是如何阻止内部实现在不同时间同时执行读写操作的线程如果封装的tcp :: socket准备好同时进行读写操作 .

在这个问题的最后一个答案结尾处的评论boost asio - SSL async_read and async_write from one thread声称对ssl :: stream的并发写入可能是段错误而不仅仅是交错,这表明该实现没有采取必要的锁来防止并发访问 .

除非实际的延迟套接字写入绑定到排队的线程/链(我看不到它是真的,否则会破坏工作线程的有用性),我怎么能确信可以排队读取和写在同一个ssl :: stream上,或者那样可能是什么?

也许async_write_some立即处理带有SSL上下文的所有数据,生成加密数据,然后变成普通套接字写入,因此不能与同一链上的读完成处理程序冲突,但这并不意味着在完成处理程序在链上排队之前,它不能与内部实现socket-read-and-decrypt冲突 . 别介意可能发生的透明SSL会话重新协商......

我注意到:Why do I need strand per connection when using boost::asio? "Composed operations are unique in that intermediate calls to the stream are invoked within the handler's strand, if one is present, instead of the strand in which the composed operation is initiated."但我不确定我所指的是"intermediate calls to the stream" . 这是不是意味着:"any subsequent processing within that stream implementation"?我怀疑不是

最后,为什么 - 为什么,为什么ssl :: stream实现不使用futex或其他没有冲突时便宜的锁?如果遵循链规则(隐式或显式),则成本几乎不存在,但否则将提供安全性 . 我问,因为我刚刚转换了Sutter,Stroustrup和其他人的宣传,C使一切变得更好更安全,对于ssl :: stream,它似乎很容易遵循某些法术,但几乎不可能知道你的代码是否真的安全 .

2 回答

  • 2

    问:但我不确定我所指的是“对流的中间调用” . 这是否意味着:“该流实现中的任何后续处理”?我怀疑不是

    文档拼写出来:

    此操作是根据对流的async_read_some函数的零次或多次调用实现的,称为组合操作 . 程序必须确保流不执行任何其他读取操作(例如async_read,流的async_read_some函数或执行读取的任何其他组合操作),直到此操作完成 . DOC


    最后,为什么 - 哦 - 为什么,为什么ssl :: stream实现不使用futex或其他没有冲突时便宜的锁?

    您无法在异步操作中保存futex,因为任何线程都可以执行完成处理程序 . 所以,你仍然需要这里的股,使futex多余 .


    对此问题的最后一个答案结尾处的评论提升asio - 来自一个线程的SSL async_read和async_write声称并发写入ssl :: stream可以段错误而不仅仅是交错,表明实现没有采取必要的锁来防止并发访问 .

    见前一条目 . 不要忘记多个服务线程 . 数据竞赛是Undefined Behaviour


    TL; DR

    长话短说:异步编程是不同的 . 这有很好的理由 . 你必须调整你的想法 .

    Strands通过在异步调度程序上抽象顺序执行来帮助实现 .

    这使得您无需知道调度是什么,运行了多少服务线程等 .

  • 2

    答案是boost ssl :: stream实现在内部使用strands进行SSL操作 .

    例如,async_read_some()函数创建openssl_operation的实例,然后调用strand_.post(boost :: bind(&openssl_operation :: start,op)) . [http://www.boost.org/doc/libs/1_57_0/boost/asio/ssl/old/detail/openssl_stream_service.hpp]

    假设所有必要的内部ssl操作都在此内部链上执行,从而序列化对SSL上下文的访问,这似乎是合理的 .

相关问题