Детальная спецификация bittorrent DHT
В своем новом проекте выходного дня я решил написать битторрент-клиент с нуля, без готовых к использованию библиотек вообще. После двух дней поиска документации я уже собираюсь сдаться:smile:. Я знаю, что есть BEP, но их далеко недостаточно для понимания всей спецификации. Прочитав намного больше, я думаю, что протоколы трекера и однорангового узла кажутся устаревшими и простыми для понимания / реализации (да, я знаю, чтобы написать хороший код с балансом, выбором одноранговых узлов, оптимизацией, это не так просто, как я только что сказал, но все, что я хочу, - это научиться основам, а не конкурировать с десятками хороших клиентов.)
Итак, я решил начать с DHT, которая кажется более сложной и менее документированной. Когда вы перестанете искать битторрентный DHT или магистральный DHT и начнете искать kademlia DHT, у вас будет гораздо больше информации, но не так очевидно, как все это собрать.
Вот что я понимаю до сих пор (и есть пробелы, которые я надеюсь заполнить):
- Я начинаю с моего дерева DHT пустым
- использование
find_nodes
на моем узле начальной загрузки - добавьте полученные узлы к своему дереву, чтобы я мог выбрать те, которые ближе к моему собственному идентификатору
- начать выпуск
find_nodes
к выбранным и добавить их ответы в мое дерево - вернуться к 3, пока я не перестану получать неизвестные / новые узлы
- если я получу
announce_peer
сinfo_hash
чем мне надо сохранить его информацию на локальной БД (info_hash и ip / port отправителя) - если узел использует
get_peers
сinfo_hash
После этого я отправляю информацию в свою БД, в противном случае я должен отправить список более близких узлов, которые есть в моем собственном дереве (ближайший к этому info_hash) - когда я использую
get_peers
на других узлах я получу одноранговые узлы или узлы, в более позднем случае я думаю, что узлы ближе кinfo_hash
а не к себеnodeId
Итак, я должен добавить эти узлы в мое дерево или начать новое дерево на их основе? - когда я хочу объявить, я заинтересован в
info_hash
я должен использоватьannounce_peer
везде или просто к узлам сnodeId
ближе к целиinfo_hash
? Насколько достаточно ближе?
На данный момент у меня есть много узлов, идентификаторы которых ближе к моему собственному идентификатору, и информация о info_hash'es меня не особо интересует.
Я боюсь, что у меня есть гигантский глупый вопрос: почему я это сделал?
Я имею в виду: моя эгоистичная причина сделать всю эту работу - найти пиров для интересующего меня info_hash. Я понимаю, что информация об одном info_hash, скорее всего, будет сохранена на узле, идентификатор которого ближе к этому info_hash. Поэтому у меня больше шансов найти информацию, если я создаю дерево узлов ближе к info_hash, а не ближе к своему собственному идентификатору (в этот момент, если вы знаете предмет, вы уже заметили, как я потерян).
Должен ли я создать несколько деревьев? Один для меня (чтобы сохранить информацию info_hashes ближе к моему nodeID, которую люди посылают мне), а другое дерево ближе к каждому из моих целевых info_hashes, чтобы я мог получить их информацию?
Должен ли я создать одно дерево ближе к моему идентификатору узла и надеяться на лучшее при запросе этого дерева для нужных мне info_hashes?
Должен ли я сдаться, так как совершенно не понял идею, лежащую в основе DHT?
Ну, любая реальная документация, блок-схемы, любая вещь будет приветствоваться!
2 ответа
Итак, я решил начать с DHT, которая кажется более сложной и менее документированной.
Петер Маймунков и Давид Мазьер должны прочитать оригинальную статью о кадемлии "Kademlia: одноранговая информационная система на основе метрики XOR". Это упоминается довольно рано в BEP-5
если я получаю announce_peer с info_hash, я должен сохранить его информацию в локальной БД (info_hash и ip / port отправителя)
Вы принимаете объявления только в том случае, если они содержат токен, ранее выданный через get_peers
,
когда я использую get_peers на других узлах, я получу одноранговые узлы или узлы, в более позднем случае я думаю, что узлы ближе к info_hash, а не к моему собственному nodeId, поэтому я должен добавить эти узлы в свое дерево или начать новое дерево на основе их?
Вы используете временное дерево - или список, упорядоченный по идентификатору контакта относительно идентификатора цели - для итеративных поисков, поскольку они не сбалансированы с идентификатором вашего узла.
Когда я хочу объявить, меня интересует info_hash. Должен ли я использовать announce_peer везде или только для узлов с ID узла ближе к целевому info_hash? Насколько достаточно ближе?
Вы выполняете get_peers
поиск и когда это сделано, вы объявляете ближайшему набору узлов, которые вернули токен записи, и проверяете ответы, чтобы убедиться, что вы действительно получили. В случае bittorrent = 8.
Моя эгоистичная причина сделать всю эту работу - найти партнеров для интересующего меня info_hash. Я понимаю, что информация об одном info_hash, скорее всего, будет сохранена на узле, идентификатор которого ближе к этому info_hash. Поэтому у меня больше шансов найти информацию, если я создаю дерево узлов ближе к info_hash, а не ближе к своему собственному идентификатору (в этот момент, если вы знаете предмет, вы уже заметили, как я потерян).
При выполнении поиска вы не просто посещаете узлы в своей таблице маршрутизации, вы также посещаете узлы, включенные в ответы. Это делает их итеративными. Смещение таблицы маршрутизации каждого узла к их собственному идентификатору гарантирует, что ответы включают соседей все ближе и ближе к цели.
Таким образом, дело в том, что вы несете ответственность за информацию, близкую к идентификатору вашего узла, а другие узлы будут предоставлять информацию, близкую к интересующим их идентификаторам узлов. Таким образом, ваша таблица маршрутизации служит другим, а их таблица маршрутизации служит вам.
Обратите внимание, что всю информацию, содержащуюся в этом ответе, можно найти в документе BEP или Kademlia.
Просто оставляю записку о моем понимании.
Раздача торрент-контактов пиров
Поскольку все компьютеры в мире не могут хранить контактную информацию одноранговых устройств для всех торрентов, мы решили равномерно, но систематически распространять контактную информацию одноранговых устройств для торрентов по всей сети, чтобы один узел DHT («распределенная хеш-таблица BitTorrent») должен хранить только некоторую выделенную часть всей контактной информации коллег.
Ноды отвечают за одноранговые контакты торрентов с инфохешами, близкими к их идентификатору.
Все узлы в DHT, включая первоначальные раздающие, работают вместе, чтобы поместить контактную информацию однорангового торрента туда, где он принадлежит в DHT , то есть узлы с идентификаторами, наиболее близкими по метрике расстояния XOR к информационному хэшу торрент. (Примечание: информационный хеш торрента и идентификатор узла DHT имеют одинаковую длину в октетах, поэтому их можно объединить с помощью операции XOR.)
Как добраться до места, где находится торрент, чтобы получить/установить контакты его одноранговых устройств
Это означает, что если вы хотите зарегистрироваться в качестве узла торрента, вы итеративно делаете запросы (не