最近看了幾天的bitcoin的代碼,主要從網絡通信部分著手開始看的,對于一個三年多沒有寫過C++代碼的人來說,看其中的消息序列化反序列化代碼,只有一句臥艸感嘆,遂拾起多年未寫過的C++,來寫點東西。
既然是看到了比特幣的P2P網絡,何不把這個網絡上的IP全部搞下來,看看這些IP都分布在哪里,于是查看了下比特幣的網絡通信協議:兩個節點建立連接后,發起連接者發送version
命令,接受者響應verack
命令并發送version
命令,發起者響應verack
命令,如下圖:
如果把verack
和version
畫在一起,就和TCP的三步握手一樣了。交換完這幾個協議命令之后,兩個節點的連接就完全建立好了,可以發送其他的一些協議命令了。看了文檔,沒有主動獲取對端相鄰節點的協議命令,只有一個addr
命令來主動告知對端與本節點相連的節點IP。
先寫個demo再說,很簡單,從DNS seed獲取IP節點,建立連接,處理完握手之后不發送任何信息,只接受消息,打印出接收到的命令,在一大串的命令之后,收到了期盼的addr
命令,bingo!
心里大致有了一個流程圖,從DNS seed中獲取IP地址放入IP種子集合中,創建一個kqueue
(linux上是epoll
),不斷從IP種子集合中拿出一些IP,創建TCP連接,并開始監聽讀寫事件,只要收到addr
協議命令后,就從消息中取出IP地址放入IP種子集合中。
真是說起來容易,做起來難,而且還三年多沒寫過C++了,最后總算是能夠穩定的跑起來了。進過四天的連續執行,已經獲取到了7.6W+個IP地址:
用tornado
寫了個web服務,通過ip獲取地理位置信息,并做了點可視化:
我大天朝果然牛批!占比25%左右!
還可以查看其它國家的具體分布,代碼已經放在全球最大男性交友網站了,https://github.com/lt90s/BitcoinNetwork,求星星~~~