7.1 KiB
BitTorrent: участники, метаданные и проверка данных
В предыдущих опытах мы искали адрес сервиса. Теперь задача другая: найти участников, у которых есть нужный файл, и проверить полученные от них данные.
В BitTorrent участники раздачи называются пирами, а участник с полным файлом — сидом. Трекер сообщает клиенту контакты пиров. Сам файл передаётся между участниками.
Все команды выполняются из каталога seminar; подготовка стенда. Файлы и участники в опытах создаются локально.
1. Прочитать метаданные и проверить части
Файл .torrent описывает раздачу: содержит адрес трекера, сведения о содержимом и хеши частей. Рассматриваем формат BitTorrent v1 и раздачу одного файла.
Перед запуском предскажите:
- Изменится ли infohash (идентификатор раздачи), если заменить только адрес трекера или комментарий в
.torrent? - Что обнаружит проверка, если изменить один байт второй части полученного файла?
docker compose run --rm -T tools python3 bittorrent/metadata.py demo --directory /work/metadata
Скрипт создаёт файл размером 256 KiB и метаданные с частями по 64 KiB, затем выполняет обе проверки. В выводе найдите:
| Поле | Смысл |
|---|---|
announce |
Адрес трекера |
name, length |
Имя файла и размер в байтах |
piece length |
Размер части |
pieces |
Хеши частей для проверки полученных данных |
Сведения о файле и частях находятся в словаре info. В v1 infohash вычисляется как SHA-1 от исходных байтов этого словаря, записанного в формате bencode — формате сериализации метаданных BitTorrent. Адрес трекера и комментарий находятся вне info, поэтому их замена сохраняет infohash, если байты info не менялись.
Для проверки файла каждая часть хешируется и сравнивается с соответствующим значением из pieces. В нашем учебном файле четыре одинаковые части, поэтому их хеши совпадают. После изменения байта проверка обнаруживает повреждение второй части — в выводе это индекс 1.
Повторите проверку повреждённого файла отдельно:
docker compose run --rm -T tools python3 bittorrent/metadata.py verify /work/metadata/lesson.torrent /work/metadata/damaged.bin
Ожидаем FAILED bad pieces: [1] и код завершения 1. Проверка подтверждает соответствие данных выбранным метаданным; доверие к самим метаданным остаётся отдельным вопросом.
2. Отключить трекер во время передачи
Предскажите: смогут ли продолжать загрузку клиент с уже найденным пиром и новый клиент, который ещё никого не знает?
В этом опыте другие способы поиска участников отключены: распределённый поиск (DHT), обмен контактами между пирами (PEX) и обнаружение в локальной сети. Новый клиент начинает без сохранённых контактов и может получить их только от трекера.
docker compose run --rm -T tools python3 bittorrent/live.py
Скрипт запускает трекер и три клиента на основе библиотеки libtorrent. Они передают файл размером 4 MiB:
- Сид регистрируется на трекере. Клиент
knownполучает его контакт и начинает загрузку. - Трекер начинает отвечать HTTP 503 — «сервис недоступен». В этот момент запускается новый клиент
fresh. knownпродолжает получать данные и завершает загрузку. Уfreshнет пиров и данных.- Трекер восстанавливается. После нового запроса
freshнаходит участников и тоже получает файл.
Сопоставьте строки TRACKER, known, fresh и PASS с этими этапами. Счётчик bytes_done показывает, сколько байтов содержимого уже есть у клиента; завершённые файлы дополнительно сверяются с исходным.
Трекер нужен для получения контактов. Продолжать обмен по уже установленному соединению можно и при его отказе. Результат для нового клиента зависит от условий: в обычной раздаче ему могут помочь другие способы обнаружения участников.
Поиск без трекера
Распределённая хеш-таблица (DHT) позволяет искать контакты участников по infohash без обращения к трекеру. Для входа в DHT клиенту всё равно нужен контакт хотя бы одного её узла.
В BitTorrent Mainline DHT используется Kademlia. В следующем разделе разберём Chord — другой алгоритм распределённого поиска из лекции.
Исходники: чтение метаданных и проверка частей, опыты с метаданными, локальная передача. Спецификации: BEP 3, BEP 5.