一個支持并發, 支持異步/同步, 支持http/https, 支持續傳的avhttp庫
起源
問題起源于 microcai 和 jack 的一次談話。他們注意到了 HTTP 多線程下載模式,其實本質上不過是向服務器發起了多個TCP連接。使用一個線程一樣能完成這樣的工作——只要他們使用的是異步方式進行的。 boost.asio 是一個非常優秀的異步網絡庫,要是能基于 asio 開發,就能實現單線程并發下載。得益于asio的良好架構,如果單線程性能不足的時候,只需要簡單的開啟多個線程跑 asio::io_service::run() 即可。這樣是進行多線程還是單線程都可以由用戶靈活的控制。
引線
雖然 jack 和 microcai 意識到了一個基于 asio 的并發 HTTP 下載庫的重要性。但是真正導致他們動手的原因卻是一個女人 —— 貓是也。
貓據說希望開發一個某客戶端,需要用到多線程HTTP下載功能,于是向社區列位大牛求救。 microcai 告訴她,jack在一份私有項目里實現過一個多線程 HTTP 下載代碼,找他要一下, jack 說不定能剝離出來給貓用。
jack 說剝離太麻煩了,反正一直有個想用 asio 重寫一個 HTTP 并發下載庫的想法,不如重復發明一下輪子,用 asio 的方式徹底重寫一個滿意的HTTP庫。
恰逢 avbot 的 WebQQ 協議需要 HTTP 庫,但是基于 asio 的 HTTP庫目前只有urdl (也是asio作者的大作,可惜已經不維護了)可以用,于是勉強用了這個早就停止開發的urdl,而且修修補補才勉強湊合使用。
重寫一個真正合用的基于asio的異步HTTP庫確實能幫助avbot項目,于是microcai也贊成jack的決定。了解microcai脾氣的人都知道,microcai是一個堅定的反輪子黨——一切重復發明輪子的行為都要被他批判。
命名
通過討論,決定將庫的名稱命名為avhttp。av是avplayer.org社區項目的標志性前綴,http表示他是一個用于支持HTTP協議的庫。
設計
avhttp由2大部分組成:avhttp::http_stream 和avhttp::multi_download。
- avhttp::http_stream是一個異步HTTP實現。每個http_stream對象支持一個HTTP會話。這個http_stream也是 avbot 所需要的。
- avhttp::multi_download 利用http_stream進行HTTP訪問,內部通過調度邏輯組合,將復雜的多TCP下載邏輯都封裝起來。
另外包含一些支持類,比如 avhttp::url 用于解析URI字符串,avhtt::request_opts 用戶設置HTTP請求頭。
實現
jack 承當了主要的編碼工作。microcai懶人只負責罵jack,尤其是他作出了錯誤的技術決定的時候。 當 http_stream 接近完成的時候, microcai 以迅雷不及掩耳之速度將 avbot 移植到 avhttp 上。并利用變態的騰訊服務器做了第一個測試。找到了許多意料之外的bug。這個bug故事"恐怕要消失在歷史了"。
使用
avhttp 是HeaderOnly 的庫,使用的時候不需要編譯,也不用添加庫。只需要 #include <avhttp.hpp> 即可開始享受
TO BE CONTINED ...