Проектная лаборатория

Собственный BitTorrent

0 / 19этапов пройдено

Этап 10 · Основные этапы

Скачивание фрагмента

Русский перевод заданий CodeCrafters. Примеры подготовлены для Go. Выбор языка меняет команды и результаты, но не текст задания.

На этом этапе вы скачаете один фрагмент и сохраните его на диск. На следующем этапе мы объединим фрагменты в файл.

Для скачивания фрагмента программа должна отправлять пиру сообщения протокола пиров. Общая последовательность действий:

  • Прочитать торрент-файл и получить URL трекера.
    • Вы уже делали это на предыдущих этапах.
  • Выполнить GET-запрос трекеру и получить список пиров.
    • Вы уже делали это на предыдущих этапах.
  • Установить TCP-соединение с пиром и выполнить рукопожатие.
    • Вы уже делали это на предыдущих этапах.
  • Обменяться несколькими сообщениями протокола пиров, чтобы скачать файл.
    • Именно эту часть вы реализуете на этом этапе.

Сообщения пиров

Сообщение пира состоит из префикса длины сообщения (4 байта), идентификатора сообщения (1 байт) и полезной нагрузки переменного размера.

После завершения рукопожатия нужно обменяться следующими сообщениями:

  • Дождаться сообщения bitfield от пира, указывающего, какие фрагменты у него есть.
    • Идентификатор этого типа сообщений — 5.
    • Пока полезную нагрузку можно прочитать и проигнорировать: трекер этого задания гарантирует наличие всех фрагментов у каждого пира.
  • Отправить сообщение interested.
    • Идентификатор interested — 2.
    • Полезная нагрузка пуста.
  • Дождаться ответного сообщения unchoke.
    • Идентификатор unchoke — 1.
    • Полезная нагрузка пуста.
  • Разбить фрагмент на блоки по 16 КиБ (16 * 1024 байт) и отправить сообщение request для каждого блока.
    • Идентификатор request — 6.
    • Полезная нагрузка состоит из:
      • index: индекс фрагмента, начиная с нуля.
      • begin: смещение в байтах внутри фрагмента, начиная с нуля.
        • Для первого блока это 0, для второго — 2^14, для третьего — 2*2^14 и т. д.
      • length: длина блока в байтах.
        • Для всех блоков, кроме последнего, это 2^14 (16 * 1024).
        • Последний блок содержит 2^14 байт или меньше; вычислите это значение по длине фрагмента.
  • Дождаться сообщения piece для каждого запрошенного блока.
    • Идентификатор piece — 7.
    • Полезная нагрузка состоит из:
      • index: индекс фрагмента, начиная с нуля.
      • begin: смещение в байтах внутри фрагмента, начиная с нуля.
      • block: данные фрагмента, обычно длиной 2^14 байт.

Получив блоки и объединив их во фрагменты, проверьте целостность каждого фрагмента, сравнив его хеш со значением в торрент-файле.

Тестирующая система запустит вашу программу следующим образом:

$ ./your_program.sh download_piece -o /tmp/test-piece sample.torrent <piece_index>

Она проверит, что фрагмент скачан правильно.

Примечания

  • При чтении TCP можно получить только часть данных блока, поэтому накапливайте данные, пока не получите блок целиком.
  • Необязательно: для ускорения можно отправлять запросы конвейером. В статье об экономике BitTorrent рекомендуется держать одновременно 5 незавершённых запросов, чтобы избежать задержек между отправками блоков.

Проверка в вашей IDE

Нужны Node.js, Git, Go 1.24+ для тестеров и инструменты выбранного языка. Тестеры загружаются и запускаются локально; отдельным проектам нужны дополнительные системные зависимости.

Настройка проекта и IDE

1. Создайте проект один раз

node '/opt/graphlms/tools/project-lab/cli.mjs' init bittorrent ./my-bittorrent --language go

2. Откройте папку в IDE

cd ./my-bittorrent

Реализуйте требования этапа в созданном проекте.

Запустите из папки проекта

node '/opt/graphlms/tools/project-lab/cli.mjs' submit --stage nd2

Запускайте submit из папки проекта. Это локальные проверки, а не сертификаты или результаты аккаунта CodeCrafters.

Результат проверки

go / ЛОКАЛЬНО

Подключение к локальной проверке…

Здесь появится результат

Запустите submit в терминале. Страница обновляет результаты каждые 8 секунд.

GraphLMS — инженерная лаборатория роста