Re: Инетовские ф-ции WinInet Api
От: IT Россия linq2db.com
Дата: 02.07.01 13:29
Оценка:
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 на то как создаются и убиваюься процессы. Зато всё работает быстро.
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.