Протокол BitTorrent |
- Statistics
- Participants
- Translate into Russian
- Translation result
- Translation complete.
BitTorrent — это протокол для распространения файлов. Он проектировался для беспроблемной интеграции с вебом и определяет контент по URL. Его преимущество перед обычным HTTP заключается в том, что при одновременном скачивании файла несколькими клиентами, они делятся им друг с другом. Это позволяет источнику обслуживать очень большое количество скачивающих при довольно скромной нагрузке.
Схема распространения файлов через BitTorrent состоит из следующих элементов:
Обычный веб-сервер
Уникальный файл метаданных (файл с раширением .torrent)
BitTorrent-трекер (специальный сервер, координирующий соединения клиентов в сети BitTorrent)
Клиент с файлом для раздачи (клиент-источник).
Браузеры пользователей
Торрент-клиенты пользователей
В идеале на каждый файл приходится множество клиентов.
Перед тем как предоставить файлы для загрузки, осуществляются следующие действия:
1. Запускается трекер (сервер), или используется уже запущенный.
2. Запускается обычный веб-сервер, например apache, или использует уже запущенный.
3. На веб-сервере ассоциируется расширение .torrent с типом application/x-bittorrent .
4. Используя URL трекера и раздаваемые файлы, генерируется метафайл с расширением .torrent.
5. Метафайл выкладывается на веб-сервер.
6. Создается ссылка на метафайл (.torrent) с какой-нибудь веб-страницы.
7. Запускается торрент-клиент («источник»), у которого есть доступ ко всем раздаваемым файлам.
Чтобы начать загрузку, пользователь делает следующее:
1. Устанавливает торрент-клиент (если еще не установил).
2. С помощью браузера заходит на сайт трекера.
3. Кликает по ссылке на .torrent файл.
4. Выбирает, куда сохранить загружаемые через BitTorrent файлы, или продолжает прерванную закачку.
5. Ждет завершения загрузки.
6. Закрывает программу-клиент (она продолжает раздачу до этого момента).
Поддерживаются следующие типы данных для обмена информацией между клиентами и трекером:
Строки состоят из значения длинны строки (в виде десятичного числа), следующим за ним двоеточием и самой строки. Например 4:spam соответствует «spam».
Целые числа представлены набором символов: сначала идёт «i», потом десятичное число и в конце «e». Например, i3e соответствует числу 3 и i-3e соответствует числу -3. Целые числа не имеют ограничений по размеру. i-0e — неверный код. Все коды с ведущим нулем, такие как i03e, неверны, кроме i0e, который, естественно, соответствует нулю.
Списки кодируются как «l», за которым следуют элементы (тоже закодированные), за которыми следует «e». Например, l4:spam4:eggse соответствует ['spam','eggs'].
Словари кодируются как «d» со следующим за ним списком альтернативных ключей с соответствующими им значениями, за которыми следует «e». Например, d3:cow3:moo4:spam4:eggse соответствует {'cow': 'moo', 'spam': 'eggs'} и d4:spaml1:a1:bee соответствует {'spam':['a', 'b']}. Ключи должны быть строками, и должны быть указаны в отсортированном порядке (отсортированные как raw-строки, не как буквенно-числовые).
Метафайлы — это закодированные словари со следующими ключами:
announce
URL трекера.
info
Соответствует словарю с ключами, описанными ниже.
Ключ name соответствует строке, представляющей собой имя, под которым предлагается сохранить файл (или директорию). Носит рекомендательный характер.
piece length (длина части) соответствует числу байт в каждой части, на которые делится файл. С целью передачи, файлы делятся на части фиксированного размера. Все части имеют равную длину за возможным исключением последней, которая может быть урезанной. Длина части почти всегда является степенью двойки, наиболее распространена 2^18=256 Кб (BitTorrent до версии 3.2 использует 2^20=1 Мб по умолчанию).
pieces (части) соответствует строке, длина которой кратна 20-ти. Она состоит из подстрок длиной 20, каждая из которых представляет собой хэш SHA1 одной части файла с соответствующим индексом.
Также существуют ключи length (длина) и files (файлы). Один из этих ключей должен присутствовать, но не оба сразу. Если присутствует ключ length, значит загрузка представляет собой единичный файл, иначе загрузка представляет собой набор файлов, включая структуру каталогов.
В случае единичного файла, ключ length соответствует его длине в байтах.
Для других ключей случай с несколькими файлами всеравно рассматривается как один файл, за счет объединения этих файлов в порядке их расположения в списке. Ключ files хранит список файлов в виде списка словарей, содержащих следующие ключи:
length (длина) — длина файла в байтах.
path (путь) — список строк, соответствующих именам поддиректорий, последняя из которых — имя файла (список нулевой длины вызовет ошибку).
В случае единичного файла, ключ name — это имя файла, в случае загрузки нескольких файлов — это имя директории.
Запрос к трекеру методом GET имеет следующие ключи:
info_hash
SHA1 хэш закодированного значения info из метафайла, длиной 20 байт. Заметьте, что это подстрока метафайла. Это значение почти точно должно быть закодировано с помощью escape-последовательности.
peer_id
Строка длиной 20, которую этот клиент использует как свой идентификатор. Каждый клиент при запуске случайным образом генерирует свой собственный идентификатор. Это значение также почти точно должно быть закодировано с помощью escape-последовательности.
ip
Не обязательный параметр, передающий IP (или доменное имя) на котором находится этот пир. Обычно используется для источника, если он находится на одной машине с трекером.
port
Номер порта, который слушает клиент. Обычно клиенту следует пытатся прослушивать порт 6881, и если этот порт занят, то попробовать 6882, потом 6883 и т.д. до 6889.
uploaded
Общее количество отданного другим, десятичное число, записанное ascii-символами.
downloaded
Общее количество загруженного, десятичное число, записанное ascii-символами.
left
Количество байт, которое клиент все еще должен загрузить, десятичное число, записанное ascii-символами. Важно, что это значение не может быть вычислено из ключа downloaded и длины файла, так как это может быть ранее не докаченная, но восстановленная загрузка, а также есть шанс, что часть загруженных данных не пройдёт проверку целостности и эти данные должны быть загружены повторно.
event
Это необязательный ключ, который может принимать значения started (загрузка начата), completed (файл загружен полностью), или stopped (загрузка остановлена), или пустой ключ — всё равно, что ключа нет. Если ключ не представлен, значит это одно из тех оповещений, которые отправляются через определённые интервалы. Оповещение started отправляется в самом начале загрузки, а completed отправляется один раз, когда загрузка окончена. Completed не отправляется, если файл полностью присутствовал до начала раздачи. Оповещение stopped клиенты отправляют когда приостанавливают процесс загрузки.
Ответы трекера — это закодированные словари. Если в ответе трекера присутствует ключ failure reason (причина отказа), то он будет соответствовать понятной человеку строке, которая объяснит причину возникновения ошибки, и в этом случае в остальных ключах нет необходимости. Иначе ответ должен содержать два ключа: inteval (интервал) — соответствует числу секунд, которое клиент должен ждать между периодическими запросами, и peers (пиры). Peers — это список словарей, соответствующих участникам файлообмена, каждый из которых содержит ключи: peer id (идентификатор пира), ip, и port, определяющие: идентификатор пира (выбирает для себя сам), IP-адрес или доменное имя в виде строки, и номер порта, соответственно. Заметьте, что клиенты могут производить запросы не выжидая указанных интервалов, если происходит событие или им требуется больше пиров.
Если вы хотите как-либо расширить возможности метафайлов или запросов к трекеру, пожалуйста свяжитесь с Брэмом Кохеном (Bram Cohen), чтобы быть уверенным в совместимости расширений.
Протокол BitTorrent работает поверх TCP. Для его эффективной работы не требуется какая-либо дополнительная настройка сокетов.
Соединения пиров симметричны. Сообщения, отправляемые в обоих направлениях, выглядят одинаково, и данные могут передаваться в обоих направлениях.
Протокол обращается к частям файла по индексу, описанному в метафайле, начиная с нуля. Когда пир заканчивает загрузку части и проверяет соответствие хешей, он оповещает всех известных ему пиров о том, что у него есть эта часть.
На обеих сторонах соединения хранятся два бита состояния: заблокирован (choked) или нет, и интересен (interested) или нет. Блокировка является уведомлением о том, что данные не будут отправлены до тех пор, пока не придет уведомление о разблокировании. Причины и общие технологии блокировки будут объяснены позже.
Передача данных происходит каждый раз, когда одна сторона заинтересована, а другая не блокирована. Состояние заинтересованности должно поддерживаться в актуальном состоянии все время — всякий раз, когда клиентам нечего запросить у незаблокированных пиров, они должны оповестить их об отсутствии интереса, даже будучи заблокированными. Реализация этого свойства является достаточно хитроумной, но позволяет клиентам узнать, какие пиры начнут загрузку немедленно после разблокирования.
Сразу же после создания соединения биты выставлены следующим образом: заблокирован (choked) и не заинтересован (not interested).
С целью получения большей производительности при передаче данных, клиентам следует запрашивать из очереди несколько частей за один раз (это называется «pipelining»). На другой стороне, запросы, которые не могут быть немедленно считаны и обработаны из TCP-буфера, правильнее будет поместить в очередь в памяти, чем хранить в сетевом буфере (application-level network buffer). Это позволить проигнорировать все эти запросы в случае блокирования клиента, от которого они пришли.
Протокол обмена данными между пирами (peer wire) состоит из «рукопожатия» (handshake) и следующего за ним непрерывного потока сообщений, с предшествующей каждому сообщению длиной. «Рукопожатие» состоит из десятичного числа 19, за которым следует строка «BitTorrent protocol». Первое число — это длина сообщения, сделано это в надежде, что новые протоколы будут делать также, и таким тривиальным образом будут отличаться друг от друга.
Все последующие целые числа, отправляемые по протоколу, кодируются как четыре байта big-endian (порядок байт от старшего к младшему).
После фиксированных заголовков передаются восемь зарезервированных байт, забитых нулями во всех текущих реализациях. Если вы пожелаете расширить протокол используя эти байты, пожалуйста свяжитесь с Брэмом Кохеном, чтобы убедиться, что все расширения совместимы.
Далее следуют SHA1 хэш закодированного значения info из метафайла, длиной 20 байт. (Это то же самое значение, которое содержится в ключе info_hash, отправляемом трекеру, только здесь он исходный, а не цитируемый). Если обе стороны не отправляют одно и тоже значение, то они разрывают соединение. Есть одно возможное исключение — если клиент хочет производить несколько загрузок через один порт, он может ожидать входящие соединения, чтобы получить хэш загрузки первым, и отвечать аналогично, если загрузка есть в его списке.
После хэша загрузки следует идентификатор пира, длиной в 20 байт, который указывается в запросах трекеру и содержится в списках пиров в ответах трекера. Если идентификатор пира принимающей стороны не соответствует тому, который предполагает инициирующая сторона, то он разрывает соединение.
Вот и все, что необходимо для начала обмена. Далее следует поток в котором чередуются поля длинны и сообщения. Сообщения с нулевой длинной используются для удержания соединения и игнорируются. Такие сообщения (с нулевой длинной) обычно отправляются каждые две минуты, но необходимо отметить, что таймауты могут истечь намного раньше в случае ожидания данных.
Все сообщения с ненулевой длинной начинаются однобайтовым полем, в котором содержится тип сообщения.
Возможные значения:
0 - заблокирован (choke)
1 - разблокирован (unchoke)
2 - заинтересован (interested)
3 - не заинтересован (not interested)
4 - имею (have)
5 - битовое поле (bitfield)
6 - запрос (request)
7 - часть (piece)
8 - отмена (cancel)
Сообщения «заблокирован», «разблокирован», «заинтересован», и «не заинтересован» не имеют дополнительных полей.
Сообщение «битовое поле», если оно есть, всегда отправляется первым. Его дополнительное поле содержит битовые флаги индексов. Флаги для индексов частей, которые клиент отправил, установлены в единицу, остальные же в ноль. Клиенты, у которых пока ничего нет, могут пропустить сообщение «битовое поле». Флаги первого байта поля соответствуют индексам от 0 до 7 от старшего бита до младшего соответственно. Следующие от 8-го до 15-го и так далее. Неиспользуемые биты в конце последнего байта устанавливаются в 0.
Дополнительное поле сообщений типа «имею» — это число, обозначающее индекс части, которую клиент только что скачал и проверил ее хеш-значение.
Сообщение типа «запрос» содержит индекс, начало и длину. Последние два компонента это байтовые смещения. Длина в общем случае задается в форме степени двух, если она не будет обрезана концом файла. Все текущие реализации используют 2^15 и закрывают соединение, если запрос больше чем 2^17. (От переводчика: не пойму, что есть длина? Это байтовое смещение конца или это кол-во байт? И точное число или степень двойки?)
Сообщения типа «отмена» содержат те же поля, что и сообщения типа «запрос». Обычно они посылаются в конце закачки, во время так называемого «эндшпиля». Когда закачка почти завершена, последние несколько частей файла, как правило, закачиваются через узкую пропускную полосу, что занимает очень много времени. Чтобы обеспечить быструю загрузку последних нескольких частей, в определенный момент все не закачанные клиентом части запрашиваются у всех, с кого клиент производит загрузку. Чтобы это не было слишком неэффективно, клиент посылает всем сообщение «отмена», каждый раз, когда полностью скачивает часть файла.
Сообщение типа «часть» содержит индекс, начало и саму часть. Заметьте, что они полностью аналогичны полям сообщения типа «запрос». Есть вероятность, что придет не ожидаемая в данный момент часть, в случае если сообщения «заблокирован» и «разблокирован» посланы быстро друг за другом и/или передача становится очень медленной.
Как правило, клиенты качают части в случайном порядке, благодаря чему исключается проблема недостатка или перенасыщения частями любого из пиров.
Блокирование используется по нескольким причинам. Очень не просто контролировать перегрузку TCP, при пересылке, использующей много соединений. Также, блокирование позволяет каждому пиру использовать алгоритм «я тебе — ты мне», чтобы гарантировано получать высокую скорость загрузки.
В настоящее время используется лишь алгоритм блокирования, описанный ниже. Очень важно, чтобы все новые алгоритмы работали одинаково хорошо как в сети, где используются только они, так и в сети, использующей в основном текущий алгоритм.
Есть несколько критериев, которым должен удовлетворять хороший блокирующий алгоритм. Он должен обрабатывать несколько одновременных раздач, чтобы обеспечить хорошую производительность по протоколу TCP. Он должен избегать быстрых последовательных блокировок и разблокировок — явления, известного как «мерцание». Он должен обмениваться с теми пирами, которые позволили ему скачивать (отвечать взаимностью). Наконец, он должен пробовать неиспользуемые соединения время от времени, чтобы выяснить, насколько они могут быть лучше текущих, это так называемое оптимистичное разблокирование.
Применяемый в настоящее время алгоритм блокирования избегает эффекта мерцания, изменяя блокировку только раз в десять секунд. Он поддерживает взаимный обмен и количество раздач разблокированием четырех пиров, у которых лучшая скорость скачивания и есть заинтересованность. Пиры, имеющие лучшую скорость отдачи, но не заинтересованные — разблокируются, а если после этого они становятся заинтересованными, то наихудший раздающий блокируется. Как только файл загружен полностью, в решении вопроса о разблокировании скорость отдачи становится предпочтительнее скорости загрузки.
Что касается оптимистической разблокировки: в каждый момент есть один пир, который разблокирован вне зависимости от его скорости отдачи (если он заинтересован, то считается одним из четырех разрешенных качающих). Оптимистически разблокированный пир меняется каждые 30 секунд. Чтобы у такого пира была достаточная возможность получить целую часть для раздачи, его новые соединения оптимистически разблокируются в три раза чаще, чем у любого другого пира.
