Mainline DHT — это название, данное распределенной хэш-таблице (DHT) на основе Kademlia , используемой клиентами BitTorrent для поиска пиров через протокол BitTorrent . Идея использования DHT для распределенного отслеживания в BitTorrent была впервые реализована [1] [2] в Azureus 2.3.0.0 (теперь известной как Vuze ) в мае 2005 года, после чего она приобрела значительную популярность. Не связанная с этим, но примерно в то же время, BitTorrent, Inc. выпустила похожую DHT в своем клиенте под названием Mainline DHT и таким образом популяризировала использование распределенного отслеживания в протоколе BitTorrent. Измерения показали, что к 2013 году одновременное число пользователей Mainline DHT составляло от 16 до 28 миллионов, с внутридневными изменениями не менее 10 миллионов. [3]
Основной DHT основан на популярной конструкции Kademlia DHT. [4] До использования DHT для распределения пиров трекеры были единственным методом поиска пиров. [5] Ключевой особенностью использования DHT вместо трекеров является то, что децентрализованный подход благоприятствует природе протокола BitTorrent. DHT работает путем распространения списков пиров, идентифицированных хэшем SHA-1 торрента.
Каждый клиент случайным образом выбирает 160-битный идентификатор узла, а расстояние между узлами вычисляется с помощью XOR их идентификаторов. Основной DHT использует k-buckets для отслеживания известных узлов.
Чтобы загрузить файл, клиент сначала запрашивает свои k-buckets для узлов, ближайших к торренту info_hash
. Он подключается к этим узлам, чтобы найти пиров. Если пиры найдены, клиент загружает файл из нескольких источников, аналогично стандартному протоколу BitTorrent. [5]
SHA-1-хэш торрента, infohash , является синонимом ключа Kademlia, который используется для поиска пиров (значений) в оверлейной сети. Чтобы найти пиры в рое, узел отправляет запрос get_peers с infohash в качестве ключа (эквивалент Kademlia FIND_VALUE ) ближайшим известным узлам (по отношению к расстоянию ключа). Как и в Kademlia, если узел не возвращает значение (пиры), он продолжает выполнять итеративную операцию. Однако после того, как поиск исчерпан, клиент также вставляет контактную информацию пиров для себя в отвечающие узлы с идентификаторами, наиболее близкими к infohash торрента.
Узлы используют дополнительную меру, известную как токен , чтобы гарантировать, что другие не подпишут другие хосты для торрентов. Возвращаемое значение для запроса пиров включает это непрозрачное значение. Чтобы узел объявил, что его контролирующий пир загружает торрент, он должен предоставить токен, полученный от того же запрошенного узла в недавнем запросе пиров. Когда узел пытается «объявить» торрент, запрошенный узел проверяет токен по IP-адресу запрашивающего узла.
Основной DHT использует хэш SHA-1 IP-адреса, объединенного с секретом, который меняется каждые пять минут для значения токена. Принимаются токены возрастом до десяти минут.
Узел в Mainline DHT состоит из комбинации IP и порта. Узлы взаимодействуют через протокол RPC , называемый KRPC . KRPC — это простой протокол, который состоит из узлов, отправляющих сообщения (запросы, ответы и ошибки), содержащие закодированные словари по UDP .
Сообщение KRPC представляет собой единый словарь с двумя ключами, общими для каждого сообщения, и дополнительными ключами в зависимости от типа сообщения. Каждое сообщение имеет ключ «t» со строковым значением, представляющим идентификатор транзакции. Этот идентификатор транзакции генерируется запрашивающим узлом и отражается в ответе, поэтому ответы могут быть соотнесены с несколькими запросами к одному и тому же узлу. Идентификатор транзакции должен быть закодирован как короткая строка двоичных чисел, обычно достаточно двух октетов, поскольку они охватывают 2^16 невыполненных запросов. Другой ключ, содержащийся в каждом сообщении KRPC, — это «y» с односимвольным значением, описывающим тип сообщения. Значение ключа «y» может быть одним из «q» для запроса, «r» для ответа или «e» для ошибки.
Запросы или словари сообщений KRPC со значением "y" "q" содержат два дополнительных ключа: "q" и "a". Ключ "q" имеет строковое значение, содержащее имя метода запроса. Ключ "a" имеет значение словаря, содержащее именованные аргументы запроса.
Ответы, или словари сообщений KRPC со значением "y" "r", содержат один дополнительный ключ "r". Значение "r" представляет собой словарь, содержащий именованные возвращаемые значения. Ответные сообщения отправляются после успешного завершения запроса.
Ошибки, или словари сообщений KRPC со значением "y" "e", содержат один дополнительный ключ "e". Значение "e" — это список. Первый элемент — это целое число, представляющее код ошибки. Второй элемент — это строка, содержащая сообщение об ошибке. Ошибки отправляются, когда запрос не может быть выполнен.
Ведра структурированы иначе, чем в Kademlia. Вместо списка из 160 ведер BitTorrent начинает только с одного ведра. Когда ведро заполняется, может произойти одно из двух:
Разделение — это операция, которая происходит только в том случае, если наш собственный идентификатор узла попадает в диапазон ведра. Разделяемое ведро заменяется двумя новыми ведрами, каждое из которых имеет половину диапазона старого ведра, а узлы из старого ведра распределяются между двумя новыми.
Такая реализация контейнера имеет два преимущества:
Mainline DHT впервые был включен в версию 4.2.0 программного обеспечения BitTorrent (ноябрь 2005 г.). С тех пор он был реализован рядом других клиентов: