BT源代碼學習心得(十三):客戶端源代碼分析(對等客戶的連接建立及其握手協議)

BT源代碼學習心得(十三):客戶端源代碼分析(對等客戶的連接建立及其握手協議)

發信人: wolfenstein (NeverSayNever), 個人文集
標  題: BT源代碼學習心得(十三):客戶端源代碼分析(對等客戶的連接建立及其握手協議)
發信站: 水木社區 (Wed Aug 17 11:48:45 2005), 文集
(本文包含HTML標記,終端模式下可能無法正確瀏覽)
    上一次我們分析到了一個客戶是如何得獲取到對等客戶的信息,現在終於要開始建立連
接了。這一次我們將分析兩個對等客戶之間的連接的建立以及連接對象爲它們之間通信提供
的基礎框架設施。
    Encoder.start_connection建立到某個對等客戶的連接。dns參數是IP地址和端口號,
id是對方的peerid。首先檢查對方的IP地址是否在banned列表內,如果在,直接返回,就是
說不會再和對方建立連接。這就是通過一個黑名單的機制,避免和某些對等客戶連接。這個
黑名單也有一些生成的策略,後面我們可以看到,通常是發現某個對等客戶傳來的錯誤數據
過多就將其加入到黑名單中。然後,當然對方id不能等於自己的id,以及在已有的連接中進
行查找,不能重複連接。然後是檢查連接數,如果連接數大於某個配置值,那麼將這個連接
的信息暫存入spares列表,日後再取出來。接下來就可以讓RawServer進行網絡連接了。如
果網絡連接成功建立,那麼一個新的Connection對象就會被創建,並且該網絡連接的數據處
理對象(data_came_in)也會被交給這個Connection對象。
    現在我們來看看網絡的另外一頭,就是說對方收到連接後會執行什麼代碼。由於在
Multitorrent中定義了一個SingleportListener來偵聽本地端口,也就是說,所有的外部網
絡連接的處理對象都是這唯一的SingleportListener,那麼很自然,對方收到連接後,
SingleportListener.external_connection_made會被調用。注意到SingleportListener和
Encoder都定義在BitTorrent/Encoder.py中,看來作者是認爲它們關係比較緊密。
SingleportListener.external_connection_made中所做的事情也是創建一個Connection對
象,並且完成網絡連接的數據處理對象的重定位工作。
    兩種不同的情況都會有一個新的Connection對象被創建,但是初始化它們的參數不太相
同,另外它們都會被維護到一個字典中,Encoder中的這個字典記錄了某個種子文件下載任
務的所有連接,而SingleportListener中的這個字典記錄了所有外部來的連接(就是說,還
不知道應該把它們交由哪個Encoder進行管理)。
    現在我們來看Connection對象被創建時所做的初始化工作。第一個參數是encoder,就
是說該Connection對象屬於哪個encoder管理,這個參數也有可能是SingleportListener,
第二個參數就是由RawServer創建的SingleSocket對象,它通常是用來作爲所有連接的字典
中的關鍵字,另外可以用它來完成具體的網絡讀寫操作。第三個參數是id,指的是對方的
peerid,如果是外部連接(SingleportListener處理的),那麼這個參數是None,即還不知道
對方的peerid,最後一個參數是一個布爾值,說明該連接是本地發起的
(Encoder.start_connection)還是外部連入的
(SingleportListener.external_connection_made)。開始的初始化工作基本上是對一些變
量的初始化,注意到_reader變量,_read_messages()函數是一個多次使用了yield關鍵字的
函數,所以這裏_read_messages沒有被執行,然後下面的_next_len的賦值部分,使
_read_messages()執行了一些,即開始的yield 1。這樣_next_len就等於1,且
_read_messages()函數執行凍結在了這裏。最後,如果是主動連接的話,那麼就往網絡上發
送後面的那一串東西。如果不是主動連接就不用了。發送的那些數據就是BT通信協議的握手
部分的內容。
    現在就可以來看Connection.data_came_in函數是如何處理到來的網絡數據。
_next_len表示的是下一條完整的消息的長度,_buffer是緩衝區中暫存的信息(因爲還沒有
達到_next_len的要求),_buffer_len則是緩衝區中的信息的長度。每一次試圖從網絡數據
s中得到組成下一個完整的消息的數據,因此首先計算長度,_next_len-_buffer_len說明要
從s中得到多少數據。如果s中沒有這麼多數據就把s中的數據暫存到緩衝區中,然後就返回
。這樣下一次調用data_came_in時就可以繼續組建需要的數據了。如果s中有足夠的數據,
則將其組成合適的長度(_next_len),放入_message中,以方便處理。然後讓
_read_messages()繼續往下執行。如果s中還有數據,則while循環要繼續進行。我們看到,
在data_came_in的這種設計框架下,_read_messages()函數每次yield一個值,當它接下來
恢復執行時,_message中就已經有它要的值了。
    這樣,_read_messages()就可以專門處理協議。我們現在就可以對比本地發起的網絡連
接的初始化過程中發出的那個握手字符串來分析握手協議。首先yield 1,然後一個字節的
數據進入了_message,這就是chr(len(protocol_name)),協議名稱的長度。通過把這個字
符還原成整數,看它是否和協議名稱相同。接下來yield len(protocol_name),然後進入
_message的數據就是protocol_name,檢查看它是否是'BitTorrent protocol',然後yield
8,這是8個字節的保留串,不用進行任何處理,繼續yield 20。這是download_id的值,
encoder.download_id是什麼呢?就是種子文件的infohash。然後檢查
self.encoder.download_id,如果是None,那麼說明這個Connection對象是
SingleportListener建立的,就是說這是網絡中來的連接,因此程序運行到這裏就可以做的
一件事情就是看看這個infohash到底是本地的哪個下載任務,更準確的說,這個
Connection對象應該交給哪個Encoder進行管理。所以它調用了encoder.select_torrent(其
實就是SingleportListener.select_torrent),這個函數從維護的torrents字典中根據
infohash查找對應的Encoder,然後讓Encoder.singleport_connection進行Connection的交
接。在Encoder.singleport_connection中做的事情包括檢查對方的IP是否在banned列表中
,否則拒絕其連接。然後將Connection對象添加到自己維護的字典中,並且將其從
SingleportListener的字典中刪除,然後將Connection的encoder指向自己,這樣這個
Connection就正式歸這個Encoder管理了。再返回到_read_messages()函數中,對
encoder.download_id的檢查就可以證明以上過程是否成功完成了。下面一個elif則是主動
的連接,對方返回的download_id在_message中,如果和自己的encoder.download_id不符,
則中斷該連接。下面檢查是否是本地發起的連接,如果不是本地發起的連接,則也向對方發
送握手協議(這樣對方的_read_messages()函數也可以開始運行了)。接下來yield 20,得到
peer id。這是對方的ID,Connection中保留的id都是對方的ID,自己的ID保留在Encoder中
。下面的這一段代碼對得到peer id進行處理,如果需要則保留到自己的id變量中,並且根
據自己的Encoder的Connection字典進行檢查,以避免兩個對等客戶在同一種子文件下載任
務中的重複連接。
    在握手協議的最後一步調用了Encoder.connection_completed,說明這個連接建立成功
,可以正式進行數據的交互了。在這個函數中做的工作就是爲這個Connection生成一個
Upload和SingleDownload對象,並且把這個Connection交給Choker進行管理。
    回到_read_messages()中,下面我們可以看到,握手協議已經成功完成,開始傳送其它
數據。每一條消息都分割成一個四字節長的長度和消息本身,因此while循環中不斷的
yield 4和yield l,然後_got_message來處理每個消息。
    通過這一次的分析,我們知道了兩個對等客戶之間的連接的握手協議,以及Encoder,
Connection,Upload,SingleDownload這些基本對象在連接建立時的基本關係。下一次就可
以開始分析BT通信協議中的其它部分。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章