我正在寻找修改Boost Asio HTTP Server 3 example的最佳方法,以维护当前连接的客户端列表。
如果我将示例中的server.hpp修改为:
class server : private boost::noncopyable
{
public:
typedef std::vector< connection_ptr > ConnectionList;
// ...
ConnectionList::const_iterator GetClientList() const
{
return connection_list_.begin();
};
void handle_accept(const boost::system::error_code& e)
{
if (!e)
{
connection_list_.push_back( new_connection_ );
new_connection_->start();
// ...
}
}
private:
ConnectionList connection_list_;
};
然后我弄乱了连接对象的生命周期,使得它不会超出范围并断开与客户端的连接,因为它仍然在ConnectionList中维护了引用。
如果我的ConnectionList被定义为typedef std::vector< boost::weak_ptr< connection > > ConnectionList;
,那么我冒着客户端断开连接并使其指针无效的风险,而有人正在GetClientList()
使用它。
任何人都有关于良好和良好的建议安全的方法吗?
谢谢, PaulH
答案 0 :(得分:4)
HTTP是无状态的。这意味着甚至很难定义“当前连接的客户端”的含义,更不用说在任何给定时间跟踪哪些客户 。 真正“当前客户端”的唯一时间是从接收请求到服务请求的时间(通常只有几毫秒)。即使在下载一页的过程中也不会保持连接 - 而是请求并单独发送页面上的每个项目。
处理此问题的典型方法是使用相当简单的超时 - 客户端在发送请求后被视为“连接”了一段任意长度的时间(几分钟)。某种cookie用于标识在特定请求中发送的客户端。
您所谈论的其余部分只是确保您用来保存连接信息的集合是线程安全的。您有一个添加连接的线程,一个删除它们的线程,以及使用列表中当前数据的N个线程。标准集合不保证任何线程安全,但周围还有其他一些。
答案 1 :(得分:2)
抱歉,我没有足够的声誉发表评论,所以我会在这里写下来。
回答评论: “HTTP无状态” - 但连接是有状态的! 请仔细阅读HTTP / 1.1文档,默认行为是“Connection:keep-alive”,因此如果您实现HTTP服务器,则必须等待同一连接上的其他请求。这对HTTPS尤其重要,通过减少握手次数节省大量时间。这就是每个符合要求的服务器必须了解如何保持连接的原因。
关于这个问题,你在“连接”类中有一些逻辑 - 在异步操作的每个处理程序中,你要么启动另一个异步操作,要么停止整个链(错误,一切都完成等等)
在“连接”类中编写一个函数,如tell_server_im_done,在该函数中告诉您的“服务器”实例将自己从列表中删除。您应该为“连接”构造函数提供指向服务器对象的指针或引用,以使其正常工作。
关于多线程的建议:首先在单线程中执行所有操作。您需要很好地理解线程,以便使用多个线程完成所有操作,因此如果您的服务器没有过载,请尽可能保持单线程。 :)