2009-11-03 40 views
3

我在尋找修改Boost Asio HTTP Server 3 example以維護當前連接客戶端列表的最佳方法。boost asio:維護連接客戶端列表

如果我從例如作爲修改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

回答

4

HTTP是無狀態的。這意味着甚至難以定義什麼「當前連接的客戶端」的含義,更不用說在任何給定時間跟蹤哪些客戶端是。唯一一次有確實是「當前客戶端」是從收到請求到服務請求的時間(通常只有幾毫秒)。即使下載一個頁面,連接也不會保留 - 相反,頁面上的每個項目都被請求並單獨發送。

處理此問題的典型方法是使用相當簡單的超時 - 在發送請求後,客戶端被視爲「連接」了一段任意長度的時間(幾分鐘)。某種類型的cookie用於識別在特定請求中發送的客戶端。

你談論的其餘部分只是確保你用來保存連接信息的集合是線程安全的。您有一個線程添加了連接,一個線程刪除了它們,還有N個線程使用當前列表中的數據。標準集合不保證任何線程安全性,但其他人也可以這樣做。

2

對不起,我沒有足夠的聲望來評論,所以我會寫在這裏。

對評論的答案: 「HTTP是無狀態的」 - 但連接已經完成! 請仔細閱讀HTTP/1.1文檔,默認行爲是「連接:保持活動」,所以如果您實現HTTP服務器,您必須等待同一連接上的另一個請求。這對HTTPS尤其重要,通過減少握手次數節省大量時間。這就是爲什麼每個符合要求的服務器都必須瞭解如何保持連接。

關於這個問題,有一定的邏輯在你的「連接」類 - 在異步操作的每一個處理程序,你要麼啓動另一個異步操作或停止整條產業鏈(錯誤,完成這一切,等)

在你的「連接」類中寫入一個函數,如tell_server_im_done,在該函數中告訴你的「服務器」實例將你自己從列表中刪除。你應該給你「連接」構造函數一個指向你的服務器對象的指針或引用,以使其工作。

關於多線程的建議:先在單線程中做所有事情。您需要對線程有很好的理解,才能在多個線程中完成整個任務,所以如果您的服務器沒有超載,請儘可能保持單線程。 :)