Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Indy все-таки дерьмо? (https://forum.antichat.xyz/showthread.php?t=200146)

Xieon 28.04.2010 20:33

Indy все-таки дерьмо?
 
В общем, возникла задача слить с одного сайта большое количество файлов и перезалить в другое место. В качестве этого "другого места" был выбран Народ.Диск от яндекса (всякие айфолдеры и рапидшары по сравнению с ним - полное УГ, имхо). Файлов много, тысячи. Только не спрашивайте, зачем мне это :) Для затравки я написал скриптик на PHP+curl, ищущий, скачивающий и закачивающий файлы, он отлично работал, но скорость меня не устраивала, поэтому я переписал его на Delphi+Indy, процесс пошел гораздо веселее)

Через полдня все файлы, наконец, перекачались, я расслабился, думал даже попить кофе...и тут мне в голову пришла мысль сверить хэши md5 у оригинальных файлов и закачанных на Народ, благо можно их прочитать на страницах файла, и что оказалось? У каждого пятого моего файла на Народе хэш не совпал (ровно 20%). Проверил - архивы действительно битые...Буквально 10-20 байт разница, но битые. Пи**ец.

Народ - несмотря на свои преимущества, довольно криво работает и все же я не думаю, что настолько криво, что неправильно заливает файлы. И еще - я проверил, оказалось, что среди тех файлов, которые заливал PHP скрипт, ни одного битого нет. Судя по всему, проблема в Indy (IdHTTP). Да и я не раз слышал, что Indy, в котором и так багов куча, криво работает в потоках. Знающие люди, скажите, пожалуйста, это из-за него так?)

Если из-за него, то на что переписать прогу? TClientSocket из VCL? Wininet? Winsock?

P.S. Все HTTP-заголовки, отсылаемые прогой, совершенно идентичны тем, что отсылает браузер, проверено сниффером, так что дело не в них.

ZdezBilYa 28.04.2010 20:39

Никогда никаких проблем по использованию Indy в потоках не было

GhostOnline 28.04.2010 21:08

Есть еще библиотека Synapse, но хз как она
А вообще, перепиши все это на винсок, тогда если у тебя не будет получаться будешь винить только себя

zeppe1in 28.04.2010 21:16

Synapse круче инди. а на сокетах наверное запарно будет писать, хотя конечно же это лучший вариант.

Chrome~ 28.04.2010 22:50

Может быть ты не совсем правильно отправлял файл?
Нужно анализировать все возможные ошибки, вплоть до того, что соединение может потеряться.
Если честно, то я не считаю, что это ошибка Indy, хотя я не являюсь поклонником данного компонента.

Xieon 29.04.2010 00:54

Хм, ну а что я делаю не так? Все стандартно, создаю мультипарт-формдата, добавляю файл, делаю пост...Если оборвалось подключение или еще что-то - вываливается исключение, файл пропускается. Других способов контроля закачки там вроде нет.

Synapse? Попробую, спасибо.

alexpro2004 29.04.2010 12:26

какая версия инди ?

Xieon 30.04.2010 00:12

Delphi 2009, там десятая вроде. Через SVN не обновлял.

greki_hoy 30.04.2010 01:20

на винсок можно так две апи
Код:

download_file(... );
upload_file(... );

сделать их рабочими элементами пула потоков
надо например скачaть делаеш асинхронный вызов
Код:

DOWNLOAD_INFO Args = malloc(sizeof(Args));
Args.Link = strdup(link);
Args/... еще что то
QueueUserWorkItem(download_file, &Args, WT_SET_MAX_THREADPOOL_THREADS(0, 12));
или
QueueUserWorkItem(upload_file, &Args, WT_SET_MAX_THREADPOOL_THREADS(0, 12));

и все следующие запросы в очередь можно ставить асинхронно
можно например выдать 12 запросов на ввод вывод
12 файлов скачается за время одного лиш бы канал позволял :)
в чем плюс потоки не надо создавать и разрушать так часто
после выполнения рабочего элемента этот же поток в пуле ждет следующий запрос
а если нет свободных все 12 заняты вводом выводом и канал широкий
то можно еще 12 добавить венда тут же создаст еще 12 потоков
и передаст им рабочие элементы а после если долгое время запросов не будет
начнет очищать пул от лишних потоков
все это флагами одного из параметров QueueUserWorkItem
регулируется :)

а это пример download_file
Код:

unsigned long __stdcall download_file(DOWNLOAD_INFO *pArgs)
{
//... формируем post ну тут элементарно
//... скачиваем тоже просто
//... освобождаем память из под аргументов
free(pArgs);
return 0;
}

если у нас 42 потока висят на вводе выводе переключений контекстов нет
имеет смысл столько создать если канал широкий за время 1 файла
скачивать 42 :)

ну и по такому же принципу написать upload_file :)
должно мега быстро работать да и скачивать можно в три - 4 потока
один файл если например сервер на одно соединение рубит скорость
но поддерживает скачивание файлов по частям :)

VernonCody 30.04.2010 16:51

Indy — говно. С потоками работает просто отвратно.
Решение: ICS


Время: 00:19