Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

MyDC.ru _ Всё о Direct Connect _ Скачивание файла большого объема с нескольких источников

Автор: nail 23.7.2012, 22:32

Пишу свой клиент на java с 0. При скачивании файла размером ~500 мб с ~10 человек файл всегда после скачивания получается нормальным, т.е. tth совпадает. Но если файл больше гига и 30-40 источников, то файл при скачивании ломается и в результате ттш у файла меняется. Выявить ошибки в алгоритме я не смог и подозреваю что их там нет. Собственно вопрос - это нормально что при передаче гигабайта парочка байт может побиться? какова вероятность таких событий и как с этим борются в существующих дц клиентах? Существуют ли способы проверять на достоверность скачанные блоки?
------------------------------------------------------
Я сравнил битый и не битый файлы и оказалось что некоторые пользователи специально вместо нужного сегмента шлют мусор. Думаю с этой проблемой не только я сталкивался... как же ее решают?

Автор: Setuper 24.7.2012, 9:21

http://mydc.ru/topic5202.html

Автор: nail 24.7.2012, 17:54

Спасибо, думаю мне это тоже пригодится. Пока не проверил, но мне кажется проблема еще может быть в одинаковых адресах у источников, если распознавать их только по адресу (без порта), то точно не определить кто есть кто и передаваемые сегменты будут перемешиваться. Однако даже в таком случае это не решает проблему с проверкой принимаемых данных. Ведь я запрашиваю определенный сегмент, а на деле пользователь может слать вместо него что ему заблагорассудится... таким образом можно сделать бота который будет бить все закачки в сети выдавая фейковые сегменты за реальные. Если в Utorrent'е это решается сверкой хеша каждого сегмента, то в дц подобной системы проверки просто нет (может и есть, но я не нашел)

Автор: nail 27.7.2012, 3:25

Поковырял я свой код 3 дня, удалось немного оптимизировать и отловить одно исключение, но проблема сохранилась.. если выкачивать файл весом ~2 гига с 20 источников, то с вероятностью 50% в итоге будет получен файл с другой ттш. Я использую сегменты для записи на винчестер 16кб, запросы делаю по 4 мб (256 сегментов) в результате в скачанном файле получаю ~1 битый кусок. Для проверки добавил сверку ADCGET и ADCSND, т.е. пользователи шлют мне то что было заказано. Вопрос в первую очередь к тем кто занимался этой задачей. Это у меня в коде какой то косяк или это нормально что сегменты могут быть побиты и во всех существующих дц клиентах выполняется перепроверка скачанных сегментов? Быть может TCP не такой и идеальный и при передаче данных бывает что не все байты доходят?
Меня также интересует если у пользователя было запрошено 4мб данных, а он отослал чуть меньше и его кикнуло по таймауту, как в таких случаях поступают дц клиенты? всё что было выкачано пускается на ветер или же записывается на диск? В моем алгоритме если приходит 3,99 мб, то на винт записываются целые сегменты (16384*255) а последний, недокачанный 256-ой сегмент выкидывается. Но быть может так нельзя делать? Может пользователь и отослал 4 мб, но маленький кусок из середины выпал и дошло только 3,99 мб?

Автор: Setuper 27.7.2012, 9:41

Ковыряй исходники клиентов.
Я вообще не пойму, ты что изобретаешь свой велосипед?
Не просто же так дедушкой всех клиентов является DC++ клиент. Вот и посмотри как там это реализовано.
Я полагаю, что большинство разработчиков клиентов не разбиралось в алгоритмах, а просто унаследовали их полностью от дедушки.

Автор: nail 27.7.2012, 16:27

Да, но ведь и большинство клиентов написаны на C++, а у меня Java. Я с самого начала так и хотел сделать, но открыв исходник DC++ я увидел там тысячи мелких файлов с непонятным содержимым. Чтобы найти нужные мне куски да и к тому же понять что в них и как происходит уйдет очень много времени. А свой велосипед я сконструировал за 4 дня, с файлами меньше половины гига работает замечательно.
Пораскинув мозгами я понял что бывает такая ситуация. Я делаю запрос на соединение с пользователем, жду секунду, если ответа нет делаю второй. Затем приходит ответ на первый запрос и начинается передача файла. В процессе передачи файла пользователь шлет ответ на 2-ой запрос и этот кусок ($Support...) записывается в файл