-
Здравствуйте.
Мне пришлось для определенных задач отказаться от моей любимой опенсорсной библиотеки ICS в пользу WinINet, т.к. по опыту последний имеет меньше проблем для конечного пользователя: не надо настраивать прокси — если работает Internet Explorer, то и WinINet функции тоже будут работать. Добавлю, что я не силен в спецификации HTTP.
Теперь проблема. Я не понимаю как должна работать функция InternetReadFile. Я не могу понять главного — это потоковое чтение или это блочное чтение?
С одной стороны TCP поточен. С другой стороны а) я видел множество примеров, где весь ответ HTTP-сервера читался одним вызовов функции InternetReadFile и б) в MSDN сказано, что InternetReadFile похожа на ReadFile, которая в синхронном режиме не является поточной.
Если функция поточная, то откуда она знает, где конец данных? У HTTP есть маркер конца запроса? Если есть, то как тогда передавать содержимое типа application/binary — ведь там может встретиться маркер конца?
Добавлю важный момент — все запросы POST.
Спасибо за ответ и понимание.
PS. Собственно откуда взялся вопрос и проблема. Изначально обмен данным у меня в системе был написан на библиотеке ICS с применением HTTP (и клиент и сервер). Не то чтобы я сам бы не написал сетевой транспорт, но я хотел, чтобы это был именно HTTP с целью в будущем сделать серверную часть на чем-то традиционном для web-a, например, на PHP, а разбираться с HTTP очень не хотелось. Все нормально работало до той поры, когда у определенных корпоративных сетей не начались разного рода подвисания. Насколько я понимаю причинно-следственная связь состоит в том, что они используют какие-то хитрые прокси. Использование WinINet решило эту проблему. Но на некоторых (например, на моей рабочей машинке WINDOWS 2000 workstation) машинках InternetReadFile возвращает меньше (пока ровно 1460 байт), чем было отдано на сервере, при том, что сервер я не менял ни капли — это тот же ICS, к которому не имеет никаких претензий ни бывший клиент на ICS, ни браузеры. Я задумался, может InternetReadFile потоковая функция и нужно читать пока не дочитаю нужное количество байт как в традиционных сокетах? Но она больше ничего не хочет возвращать при последующих вызовах. В общем сумбур в голове, а МСДН не прочищает...
-
могу поделится примером procedure TfmMain.Grab;
var
pInet, pUrl: Pointer;
Buffer: array[0..1024] of Byte;
BytesRead: Cardinal;
msData: TMemoryStream;
slText: TStringList;
bReturned: Boolean;
begin
pUrl := nil;
pInet := InternetOpen('InetPing', INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);
if pInet = nil then
begin
AddToLog('Error - InternetOpen');
Exit;
end;
msData := TMemoryStream.Create;
slText := TStringList.Create;
try
pUrl := InternetOpenUrl(pInet, PChar(edAddress.Text), nil, 0,
INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_RELOAD, 0);
if pUrl = nil then
begin
AddToLog('Error - InternetOpenUrl');
Exit;
end;
repeat
FillChar(Buffer, SizeOf(Buffer), 0);
bReturned := InternetReadFile(pUrl, @Buffer, Length(Buffer), BytesRead);
msData.Write(Buffer, BytesRead);
until (BytesRead = 0) and bReturned;
msData.Position := 0;
slText.LoadFromStream(msData); finally
if pUrl <> nil then
InternetCloseHandle(pUrl);
if pInet <> nil then
InternetCloseHandle(pInet);
msData.Free;
slText.Free;
end;
end;
-
Спасибо, но лишний раз доказывает, что ты не считаешь WinINet потоковым протоколом.
Понимаешь, все бы ничего (я тоже не счит аю протокол потоковым) - я тоже так считал, пока мой сервер не стал возвращать неполные данные, которые должны быть по идее туда засунуты (иначе как бы другие клиенты смогли их прочесть).
Ладно, чую, что сниффер мне в руки и искать кто виноват - сервер или клиент: кто не отдает данные.
-
> [2] тимохов (25.12.08 02:18)
> WinINet
это вообще то не протокол. а вот http в общем случае потоковые, т.е. можно в заголовке прописать размеры вроде, но можно и не прописывать. клиент будет считывать данные пока они не закончатся.
-
> т.к. по опыту последний имеет меньше проблем для конечного пользователя: не надо настраивать прокси — если работает Internet Explorer, то и WinINet функции тоже будут работать. Добавлю, что я не силен в спецификации HTTP.
С последней больше проблем для конечного пользователя. Так как у всех разные ie, разные сервиспаки, пачти винды, и эти либы. Куча глюков, которые невозможно контролировать своим кодом.
Данные прокси без проблем вытаскиваются из ie и применяются в Инди. Скорее всего, и в ICS тоже.
Очень плохо, кстати, что в винде нет такой глобальной настройки, как настройка прокси. Многие 'умники' вместо того, что бы юзать настройки из ie, делают собственные настройки. Лучше бы их изначально вообще не в ie сделали, а в основных настройках винды - может никто бы и не делал ничего другого.
Получаем. У аси - одни настройки, у флэшгета - вторые, у скайпа - третьи, у эксплорера - четвёртые.
Это неудобно в крайней степени. Я буку юзаю дома без прокси, а на работе - с проксёй. Приходится каждый софт ежедневно по два раза перестраивать руками. Блин, неужели этот проблема неочевидна?
-
> в винде нет такой глобальной настройки, как настройка прокси. > Многие 'умники' вместо того, что бы юзать настройки из ie, > делают собственные настройки. Лучше бы их изначально вообще > не в ie сделали, а в основных настройках винды - может никто > бы и не делал ничего другого
так они вызываются отдельно, из панели управления. Да и в реестре ключ свой - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
никто ж не сказал, что его юзать имеет право только ИЭ
-
Решил не создавать новую тему, а на эту наткнулся пытаясь нагуглить ответы на свои вопросы. Суть проблемы в следующем: посредством HttpSendRequest() отправляю POST запрос некоему ресурсу. Используя тот же хэндл, с помощью InternetQueryDataAvailable() и InternetReadFile() читаю текст страницы с результатом обработки запроса. Некоторое время все работает прекрасно и страницу я получаю. Однако, потом последние две функции неизменно рапортуют о том, что я могу скачать с сервера 0 байт или скачал 0 байт соответственно. "Потом" - это где-то спустя неделю использования этого кусочка кода. Ресурс один и тот же, изменения в код не вносились. Просто однажды утром запускаешь и получаешь пшик. Фиддлер при этом уверяет, что страница для скачивания у сервера есть и даже предлагает мне ее исходный код. Кстати, этот глюк я отмечал и ранее в других своих поделках. InternetReadFile() в определенный момент перестает читать данные с сервера. Где искать виноватого?
-
> Дмитрий Белькевич (31.12.2008 02:27:04) [4]
Эти умники возможно наткнулись на проблемы с использованием настроек из ИЕ, на вскидку вот пара
1. В ИЕ нет настроек, никто их не делал 2. В ИЕ есть настройки, но они не соответствуют действительности
Глобальная настройка тоже не подходит, я могу в разных браузерах и продуктах сделать разные настройки прокси и это правильно. Например скайп пускаю через один прокси, а ИЕ через другой и так далее. Или на работе работаю через ИЕ, а дома через Файрфокс и настройки разные.
Ноутбуки надо настраивать так, чтобы настройки автоматически брал от системы. Есть даже переключатели профилей, когда нельзя автоматом.
Проблема неочевидна, по крайней мере тебе. Ты просто ограничился своей средой, а реальность шире.
-
> clickmaker (28.01.2009 16:49:05) [5]
К тому же их минимум четыре, для разных вещей разные прокси.
-
> так они вызываются отдельно, из панели управления.
Увидел, таки есть глобальные настройки. Почему бы всему софту, которому нужно работать через прокси, не брать настройки еще и оттуда? Неудобно. В каждой программе должен быть выбор - работать через системный прокси или через свой.
> Ноутбуки надо настраивать так, чтобы настройки автоматически > брал от системы.
Как настроить, например, асю/скайп/ie/оперу что бы одним нажатием мыши включать/отключать прокси?
Сейчас я настроил асю/скайп/ie/оперу на работу через handycache. А уже его, когда нужно, перенастраиваю - либо работать напрямую, либо через прокси.
> Ты просто ограничился своей средой, а реальность шире.
Вы просто ограничились своей средой, а реальность шире. Мне неудобно.
> Ресурс один и тот же, изменения в код не вносились. Просто > однажды утром запускаешь и получаешь пшик.
А некоторым временем ранее винда обновлений не ставила? Из-за чего-то такого мы WinInet и 'списали'. После проблем ни разу не было.
-
> Например скайп пускаю через один прокси, а ИЕ через другой и так далее. у меня тоже есть отдельный прокси для локальной сети, т.е. если бы был общий прокси то для всех внутренних программ пришлось бы постоянно переключать инет/корпоративный сервер, а так у IE один у внутренних программ другой(у мазилы тот же т.к. отладка в основном в ней), никто друг другу не мешает и все счастливы... кроме тех кто предпочитает мозилу и для отладки и для серфинга... вот бы ее можно было заставить брать разные настройки проксей например параметром запуска. ну или что то типа, смысл, из под одного юзера, а то приходится делать запуск из под другого (неудобно, т.к. если что то меняется то приходится в 2х местах).
-
> Вы просто ограничились своей средой, а реальность шире. > Мне неудобно.
Моя среда шире :-)
-
> Моя среда шире :-)
У слона всё равно толще ;)
-
>А некоторым временем ранее винда обновлений не ставила? Из-за чего-то >такого мы WinInet и 'списали'. После проблем ни разу не было.
Нет, не ставила. У меня этот глюк систематический и проявляется спустя некоторое время. Создал новый проект: форма+кнопка. Тот же код - получил свою страницу. В старом проекте этот же код по прежнему повергает меня в уныние.
-
Кроме того меня терзают смутные сомнения, что по прошествии определенного времени или N запусков "форма+кнопка" тоже перестанет читать искомые данные.
-
Вопрос снят. Проблема решилась перезапуском встроенного в nod32 файрволла. Извините за беспокойство.
-
> Вопрос снят. Проблема решилась перезапуском встроенного > в nod32 файрволла. Извините за беспокойство.
Виноват Windows и Delphi, как обычно ;)
Ну это я самому себе больше...
|