В общем, возникла задача слить с одного сайта большое количество файлов и перезалить в другое место. В качестве этого "другого места" был выбран Народ.Диск от яндекса (всякие айфолдеры и рапидшары по сравнению с ним - полное УГ, имхо). Файлов много, тысячи. Только не спрашивайте, зачем мне это Для затравки я написал скриптик на PHP+curl, ищущий, скачивающий и закачивающий файлы, он отлично работал, но скорость меня не устраивала, поэтому я переписал его на Delphi+Indy, процесс пошел гораздо веселее) Через полдня все файлы, наконец, перекачались, я расслабился, думал даже попить кофе...и тут мне в голову пришла мысль сверить хэши md5 у оригинальных файлов и закачанных на Народ, благо можно их прочитать на страницах файла, и что оказалось? У каждого пятого моего файла на Народе хэш не совпал (ровно 20%). Проверил - архивы действительно битые...Буквально 10-20 байт разница, но битые. Пи**ец. Народ - несмотря на свои преимущества, довольно криво работает и все же я не думаю, что настолько криво, что неправильно заливает файлы. И еще - я проверил, оказалось, что среди тех файлов, которые заливал PHP скрипт, ни одного битого нет. Судя по всему, проблема в Indy (IdHTTP). Да и я не раз слышал, что Indy, в котором и так багов куча, криво работает в потоках. Знающие люди, скажите, пожалуйста, это из-за него так?) Если из-за него, то на что переписать прогу? TClientSocket из VCL? Wininet? Winsock? P.S. Все HTTP-заголовки, отсылаемые прогой, совершенно идентичны тем, что отсылает браузер, проверено сниффером, так что дело не в них.
Есть еще библиотека Synapse, но хз как она А вообще, перепиши все это на винсок, тогда если у тебя не будет получаться будешь винить только себя
Может быть ты не совсем правильно отправлял файл? Нужно анализировать все возможные ошибки, вплоть до того, что соединение может потеряться. Если честно, то я не считаю, что это ошибка Indy, хотя я не являюсь поклонником данного компонента.
Хм, ну а что я делаю не так? Все стандартно, создаю мультипарт-формдата, добавляю файл, делаю пост...Если оборвалось подключение или еще что-то - вываливается исключение, файл пропускается. Других способов контроля закачки там вроде нет. Synapse? Попробую, спасибо.
на винсок можно так две апи Code: download_file(... ); upload_file(... ); сделать их рабочими элементами пула потоков надо например скачaть делаеш асинхронный вызов Code: 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 Code: unsigned long __stdcall download_file(DOWNLOAD_INFO *pArgs) { //... формируем post ну тут элементарно //... скачиваем тоже просто //... освобождаем память из под аргументов free(pArgs); return 0; } если у нас 42 потока висят на вводе выводе переключений контекстов нет имеет смысл столько создать если канал широкий за время 1 файла скачивать 42 ну и по такому же принципу написать upload_file должно мега быстро работать да и скачивать можно в три - 4 потока один файл если например сервер на одно соединение рубит скорость но поддерживает скачивание файлов по частям
Все ваши беды от незнания матчасти: 1. Каждый объект инди ровным счетом ничего не знает о других объектах созданных в других потоках и существует независимо от них. По-этому утверждение "Indy — говно. С потоками работает просто отвратно." изначальное глупое, инди с потоками не работает вообще, программист с ними работает. 2. Исключения - не ошибки, это средство языка, и их надо обрабатывать, иначе исключение валит поток. ЗЫ Главный недостаток инди - это работа через исключения, новички этого не понимают и пугаются. На месте разработчиков инди я бы использовал "тихий режим" ЗЫЫ А вот доставляет/принимает ли корректно данные - другой вопрос, и я на него не знаю ответа.
Причем тут матчасть, может имел введу незнание как работает Indy? не правда, взаимоотношение есть при создании и удалении объектов Indy(но там код идеален и багов вызвать не может) На счет indy - говно : indy не говно...так катяшок) Багов уйма в версии в Delphi 7. Само собой очень много чего исправлено в текущих версиях. Но на удивлении у ТС похожая ошибка что и у меня в древней версии. Короче по не понятным причинам при скачивании файла из инета у него действительно урезаются 10-20 байт. Причем происходит мягко говоря от балды. Если что то происходит в программе от балды, то по любому это от не правильной синхронизации потоков. А не правильная синхронизация бывает если программист тупо не знает как правильно синхронизировать или тупо ошибся. На синхронизации собаку съел, до сих пор не могу найти где урезается. Кстати поговаривали что проблема с SysUtils, точнее с одной процедурой. Скачал этот модуль с данным фиксом - заработало gzip декомпрессия, а с урезанием "binary" данных не решил пока.
Может дашь четкое определение выражения "матчасть", тогда я тебе скажу что я имел ввиду Тыкни в это место, я такого не замечал Чтобы этого избежать нужно разрабатывать такую архитектуру в которой синхронизация не понадобится, ну или почти не понадобится. У мну как-то изначально она работала, может потому что у меня дельфи 2009 и инди постоянно обновляю, хз. Так-то баги конечно есть, но они не критичные. Вот например стандартный куки менеджер не использую, пришлось припилить свой, т.к. тот не со всеми сайтами корректно работал и авторизация по кукам проваливалась, несмотря на все обновления. Ну да, я заметил это по количеству тем открытых тобой про сокеты
Туплю Версия для D7, так что в твоей может что то поменяли. Файл IdComponent.pas : смотри конструктор и деструктор. Если было бы всё так просто, то синхронизация не нужна была бы. Конечно всегда её сводят к минимуму, но без неё во многих задачах ни как. Естественно. Я вообще не вижу смысла использовать их куки менеджер, если свой код в 200-300 строк(могу дать), и не надо создавать лишних классов. Согласен, RFC и API рулят, т.к. код свой, нет боязни что где то там что то не так работает, и собственно размер приложения существенно уменьшается. Но опять же изобретать велосипед не хочется, я думаю нужно просто написать свой маленький движок и юзать его. Када indy писали, тоже думали что при правильной логике работы будет 100% работать)
Ну так или иначе, если ты верно реализуешь работу своего сокетного движка, предотвратишь возникновение всевозможных ошибок, то твой вариант будет совершенно правильно работать, никаких проблем не будет возникать. Вот разработчики Indy в реале немного странно поступили. К примеру, есть ошибка в Indy 9 (точной версии не знаю, знаю, что в 10-ой этой проблемы уже нету). В классе TIdMultiPartFormDataStream, который используется для работы с Multipart forms дописывались два дополнительных ненужных байта, к одному из параметров, что почти всегда влияло на результат работы. Можете прочитать об этом хотя бы здесь: http://forum.vingrad.ru/act-ST/f-86/t-287613.html
Все так просто =) Пробовал в потоках только запросы выполнять? Куки менеджер это я так выразился чтобы было понятней, на самом деле процедура строк в 50, не стал морочиться с доменами, потому что каждый объект у меня строго для одного домена Такой уже есть - Synapse, так что опять велосипед. Это цветочки http://janych.selfip.com/Examples/Delphi/Indy/HTTP/ Хоть и про неактуальную версию, но сам факт наличия таких багов обескураживает.
Я такое часто использую, опять же по возможности, бывает что и обработку надо делать многопоточно. Synapse - уг, там единственно стоящее SSL удобно сделан, а работа с соксами и http-прокси достаточно проблематична если использовать их HTTP компонент. Если бы он хорошо поддерживал последнее и поддерживал gzip/deflate - я бы безусловно использовал бы его. Читали, знаем)
Обоснуй, на основе чего у тебя сложилось мнение, что Synapse неправильно работает с прокси? И этот компонент нельзя назвать, как ты выразился "УГ", - он довольно стабильно работает.