如何设计boost :: asio套接字或其包装的正确释放

Chr*_*isz 5 c++ tcp boost-asio

我几次尝试使用boost :: asio创建自己的简单异步TCP服务器几年后没有触及它.

我能找到的最新示例列表是:http: //www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html

我在这个示例列表中遇到的问题是(我觉得)它欺骗并且通过使tcp_connection成为shared_ptr来欺骗它,这样它就不用担心每个连接的生命周期管理了.(我认为)他们这样做是为了简洁,因为它是一个小教程,但这个解决方案不是现实世界.

如果您想在计时器或类似的东西上向每个客户端发送消息怎么办?在任何真实世界的非平凡服务器中都需要一组客户端连接.

我担心每个连接的生命周期管理.我认为自然要做的就是在tcp_server中保留一些tcp_connection对象或指向它们的指针.从OnConnect回调添加到该集合并从该集合中删除OnDisconnect.

请注意,OnDisconnect很可能是从实际的Disconnect方法调用的,在发生错误的情况下,该方法将从OnReceive回调或OnSend回调调用.

嗯,这就是问题所在.

考虑一下我们有一个看起来像这样的callstack:

tcp_connection::~tcp_connection
tcp_server::OnDisconnect
tcp_connection::OnDisconnect
tcp_connection::Disconnect
tcp_connection::OnReceive
Run Code Online (Sandbox Code Playgroud)

这会在调用堆栈展开时导致错误,并且我们正在一个已经调用了析构函数的对象中执行代码......我想,对吧?

我想每个做服务器编程的人都会以某种方式遇到这种情况.处理它的策略是什么?

我希望这个解释足够好.如果不让我知道,我将创建自己的源列表,但它将非常大.


编辑:相关

)异步C++代码中的内存管理

IMO不是一个可以接受的答案,依赖于在接收电话上使用shared_ptr作弊,仅此而已,并不是现实世界.如果服务器想要每5分钟对所有客户说"嗨"怎么办?某种集合是必要的.如果你在多个线程上调用io_service.run怎么办?

我也在提升邮件列表:http: //boost.2283326.n4.nabble.com/How-to-design-proper-release-of-a-boost-asio-socket-or-wrapper-thereof- td4693442.html

Chr*_*isz 3

虽然其他人的回答与此答案的后半部分类似,但我能找到的最完整的答案似乎来自在 Boost 邮件列表上提出相同的问题。

http://boost.2283326.n4.nabble.com/How-to-design-proper-release-of-a-boost-asio-socket-or-wrapper-thereof-td4693442.html

我将在这里总结一下,以帮助那些将来通过搜索到达这里的人。

有2个选项

1) 关闭套接字以取消任何未完成的 io,然后在 io_service 上发布断开后逻辑的回调,并在套接字断开连接时回调服务器类。然后它可以安全地释放连接。只要只有一个线程调用了io_service::run,那么当回调发生时,其他异步操作就已经被解决了。但是,如果有多个线程调用了 io_service::run,那么这是不安全的。

2)正如其他人在他们的答案中指出的那样,使用shared_ptr来管理连接生命周期,使用未完成的io操作来保持它们的活动,是可行的。如果需要的话,我们可以对连接使用weak_ptr集合来访问它们。后者是有关该主题的其他帖子中省略的花絮,这让我感到困惑。