B>Необходимо пересылать параллельно несколько разных сообщений через HTTP на сервер.
B>Клиент, который посылает сообщения выполнен в виде сервиса. Для пересылки я воспользовался интренетовскими ф-ями из набора WinInet API.
Под каким аккаунтом работает сервис?
B>Работа идет по след. схеме: InternetOpen/InternetConnect/HTTPOpenRequest B>Потом в каждой нити: HTTPSendRequest/InternetReadFile (для чтения ответа)
B>Причем для каждого сообщения создается свое соединение ,т.е. каждый раз вызывается InternetConnect/HTTPOpenRequest
Понятна...
B>Главная проблема: Сообщения отсылаются на сервер последовательно. Т.е.Wininet.dll блокирует вызовы других нитей, если в данный момент уже обрабатывается запрос от какой-либо нити.
Дакументированная фича :(
B>Таким образом, отсылается HTTPSendRequest, происходит возврат из него, далее вызывается InternetReadFile который подвисает т.к. ждет реакции от ASP (несколько секунд), но в это время также подвисают вызовы HTTPSendRequest от других нитей, пока не будет вызван InternetCloseHandle для первой нити.
Логично.
B>Что можно сделать в данной ситуации? Может нужен др. подход? Все делать на более низком уровне (через tcp/ip) или может есть какие-либо библиотеки, в которых реализована более приятная поддрежка HTTP?
Обойдёмся и wininet'ом.
B>Необходимость использовать HTTP вызвана простой возможностью переключиться на использование SSL.
Тоже правильно.
B>Была сделана попытка использовать асинхронные версии инетовских функций. Т.е. HTTPSendRequestEx, HTTPEndRequest и InternetQueryDataAvailable, плюс callback функция. B>Соединение происходит успешно, но реакция сервера не читается как следует: иногда читается но не всё, иногда вообще вылетает исключение изнтури Wininet.dll.
B>И как же вообще работает браузер, в таком случае?..
Этот вопрос я тоже себе задавал ;o)
Итак, по-порядку, я как раз только что отборолся с подобной задачей.
WinInet имеет несколько документированных недостатков.
1. Он не может работать под системным аккаунтом, странно что он у тебя работет в сервисе, не должен :). Скорее всего ты получишь отлуп если перейдёшь на SSL. Это связано с тем, что из-под системного аккаунты недоступны определённые части реестра, в том числе связанные с защитой.
2. WinInet не может обрабатывать одновременно больше двух коннекций. С помощью определйнных извратов это число можно удвоить, но это тоже не выход.
3. Нельзя одновременно использовать два запроса на одном соединении.
Как же тогда работает браузер?
Очень просто: он не работает под системным аккаунтом, он не использует больше двух соединений, он не запускает одновременно несколько запросов.
Выход я нашёл несколько кривоватый и дубовый как двери. Всю работу с WinInet я завернул в COM .EXE сервер и каждый раз при создании нового объекта создаётся копия отдельного процесса. Теперь WinInet у меня летает как трофейный мессершмидт. Только одна печаль — сердце кровью обливается, когда смотришь в TaskManager на то как создаются и убиваюься процессы. Зато всё работает быстро.
Если нам не помогут, то мы тоже никого не пощадим.