posts - 56,  comments - 12,  trackbacks - 0

          本篇文章分析 HTTPHandler 類,它在 HTTPHandler.py 文件中。

          上一篇我們講到, RawServer 只負責網絡 I/O ,也就是從網絡上讀取和發送數據,至于讀到的數據如何分析,以及應該發送什么樣的數據,則交給 Handler 類來處理。如果是用 c++ 來實現的話,那么 Handler 應該是一個接口類(提供幾個虛函數作為接口),但是 python 動態語言的特性,并不需要專門定義這么一個接口類,所以實際上并沒有 Handler 這么一個類。任何一個提供了以下成員函數的類,都可以作為一個 Handler 類來與 RawServer 配合,它們是:

           

          external_connection_made() :在建立新的連接的時候被調用

          data_came_in() :連接上有數據可讀的時候被調用

          connection_flushed() :當在某個連接上發送完數據之后被調用

           

                 HTTPHandler 就是這樣一個 Handler 類,它具備以上接口。

                 HTTPHandler 代碼很少,因為它把主要工作又交給 HTTPConnection 了。

                 我們看 HTTPHandler 類的這幾個函數:

           

          l         external_connection_made()

          每當新來一個連接的時候,就創建一個 HTTPConnection 類。

           

          l         data_came_in()

          當連接上有數據可讀的時候,調用 HTTPConnection::data_came_in() 。我們接下去看 HTTPConnection::data_came_in()

           

          我們知道, BT client 端與 tracker 服務器之間是通過 tracke HTTP 協議來進行通信的。 HTTP 協議分為請求( request )和響應( response ),具體的協議請看相關的 RFC 文檔。我這里簡單講一下。

          tracke 服務器來說,它讀到的數據是 client 端的 HTTP 請求。

           

          HTTP 請求以行為單位,行的結束符是“回車換行”,也就是 ascii 字符 \r ”和“ \n ”。

           

          第一行是請求的 URL ,例如:

          GET              /announce?ip=aaaaa;port=bbbbbbb       HTTP/1.0

           

          這行數據被空格分為三部分,

          第一部分 GET 表示命令,其它命令還有 POST HEAD 等等,常用的就是 GET 了。

          第二部分是請求的 URL ,這里是 /announce?ip=aaaaa;port=bbbbbbb 。如果是普通的上網瀏覽網頁,那么 URL 就是我們要看的網頁在該 web 服務器上的相對路徑。但是,這里的 URL 僅僅是交互信息的一種方式, client 端把要報告給 tracker 的信息,放在 URL 中,例子里面是 ip port ,更詳細的信息請看“ BT 協議規范”中 tracker 協議部分。

          第三部分是 HTTP 協議的版本號,在程序中忽略。

           

          接下來的每一行,都是 HTTP 協議的消息頭部分,例如:

          Host:www.sina.com.cn

          Accept-encoding:gzip

           

          通過消息頭, tracker 服務器可以知道 client 端的一些信息,這其中比較重要的就是 Accept-encoding ,如果是 gzip ,那么說明 client 可以對 gzip 格式的數據進行解壓,那么 tracker 服務器就可以考慮用 gzip 把響應數據壓縮之后再傳回去,以減少網絡流量。我們可以在代碼中看到相應的處理。

          在消息頭的最后,是一個空行,表示消息頭結束了。對 GET HEAD 命令來說,消息頭的結束,也就意味著整個 client 端的請求結束了。而對 POST 命令來說,可能后面還跟著其它數據。由于我們的 tracker 服務器只接受 GET HEAD 命令,所以在協議處理過程中,如果遇到空行,那么就表示處理結束。

           

           

          HTTPConnection::data_came_in() 用一個循環來進行協議分析:

          首先是尋找行結束符號:

           

          i = self.buf.index('\n')

           

          (我認為僅僅找 \n ”并不嚴謹,應該找 \r\n ”這個序列)。

          如果沒有找到,那么 index() 函數會拋出一個異常,而異常的處理是返回 True ,表示數據不夠,需要繼續讀數據。

          如果找到了,那么 i   之前的字符串就是完整的一行。于是調用協議處理函數,代碼是:

           

          self.next_func = self.next_func(val)

           

          HTTPConnection 的初始化的時候,有這么一行代碼:

           

          self.next_func = self.read_type

           

          next_func 是用來保存協議處理函數的,所以,第一個被調用的協議處理函數就是 read_type() 。它用來分析 client 端請求的第一行。在 read_type() 的最后,我們看到:

          return self.read_header

           

          這樣,在下一次調用 next_func 的時候,就是調用 read_header() 了,也就是對 HTTP 協議的消息頭進行分析。

           

          下面先看 read_type()

          它首先把 GET 命令中的 URL 部分保存到 self.path 中,因為這是 client 端最關鍵的信息,后面要用到。

          然后檢查一下是否是 GET 或者 HEAD 命令,如果不是,那么說明數據有錯誤。返回 None ,否則 return self.read_header

           

          接下來我們看 read_header()

          這其中,最重要的就是對空行的處理,因為前面說了,空行表示協議分析結束。

          在檢查完 client 端是否支持 gzip 編碼之后,調用:

           

          r = self.handler.getfunc(self, self.path, self.headers)

           

          通過一層層往后追查,發現 getfunc() 實際是 Tracker::get() ,也就是說,真正對 client 端發來的請求進行分析,以及決定如何響應,是由 Tracker 來決定的。是的,這個 Tracker 在我們 tracker 服務器源碼分析系列的第一篇文章中就已經看到了。在創建 RawServer 之后,馬上就創建了一個 Tracker 對象。所以,要了解 tracker 服務器到底是如何工作的,需要我們深入進去分析 Tracker 類,那就是我們下一篇文章的工作了。

           

          在調用完 Tracker::get() 之后,返回的是決定響應給 client 端的數據,

          if r is not None:

          self.answer(r)

          最后,調用 answer() 來把這些數據發送給 client 端。

           

          answer() 的分析,我們在下一篇分析 Tracker 類的文章中一并講解。

           

          l         connection_flushed()

          tracker 服務器用的是非阻塞的網絡 I/O ,所以不能保證在一次發送數據的操作中,把要發送的數據全部發送出去。

          這個函數,檢查在某個連接上需要發送的數據,是否已經全部被發送出去了,如果是的話,那么關閉這個連接的發送端。(為什么僅僅關閉發送端,而不是完全關閉這個連接了?疑惑)。

          posted on 2007-01-19 00:18 苦笑枯 閱讀(388) 評論(0)  編輯  收藏 所屬分類: P2P
          收藏來自互聯網,僅供學習。若有侵權,請與我聯系!

          <2007年1月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(2)

          隨筆分類(56)

          隨筆檔案(56)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 衡东县| 鹿泉市| 金平| 红河县| 马山县| 阿克陶县| 靖西县| 南京市| 五莲县| 汝城县| 万源市| 肃北| 平乡县| 土默特右旗| 睢宁县| 岢岚县| 武宣县| 临沧市| 萨迦县| 大足县| 自治县| 宾阳县| 伊金霍洛旗| 沁水县| 琼结县| 泰和县| 麦盖提县| 榆中县| 浙江省| 大连市| 驻马店市| 西青区| 芜湖市| 恩施市| 商都县| 南澳县| 惠东县| 沅江市| 元阳县| 平罗县| 长阳|