Полная асинхронность при использовании XMLHTTPRequest

Персональный блог одноименного форумчанина. Человека и парохода, не побоюсь этого сравнения :)

Модератор: tyomitch

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Полная асинхронность при использовании XMLHTTPRequest

Сообщение tyomitch » 22.07.2006 (Сб) 2:34

Кто-нибудь, прокомментируйте http://jszen.blogspot.com/2005/03/xmlht ... state.html
Мне сильно нужны "the current partial results". Как их из XMLHTTPRequest вытащить?


(Топик был отрезан от http://bbs.vbstreets.ru/viewtopic.php?t=26405 , и отчасти является логическим продолжением http://bbs.vbstreets.ru/viewtopic.php?t=26616 )
Последний раз редактировалось tyomitch 22.07.2006 (Сб) 15:51, всего редактировалось 1 раз.
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 22.07.2006 (Сб) 4:14

Вон что удалось нахачить:
Код: Выделить всё
Private Function GetText(ByVal h As XMLHTTPRequest) As String
' Вот зараза!
Dim obptr As Long, stptr As Long, cbstr As Long
CopyMemory obptr, ByVal ObjPtr(h) + &H18, 4
CopyMemory stptr, ByVal obptr + &HA4, 4
CopyMemory cbstr, ByVal obptr + &HAC, 4
GetText = Space(cbstr)
CopyMemory ByVal GetText, ByVal stptr, cbstr
End Function


потестируйте кто-нибудь с разными версиями IE, а?
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 22.07.2006 (Сб) 13:30

Ладно, раз никому кроме меня не интересно -- комментирую сам.
  • Все три свойства ResponseBody, ResponseText, ResponseStream недоступны до полной загрузки: внутри них стоит явное условие на State=4. Больше похоже на баг, чем на фичу; в любом случае, документация в рассогласовании с реализацией.
  • Стрим, который получается по ResponseStream, -- это CreateStreamOnHGlobal, в который закачана копия данных. Т.е. никакой это на самом деле не стрим, а просто необычный способ передать байтовый массив. Возможности вытянуть из XMLHTTPRequest настоящий стрим, в котором по мере загрузки появляются новые данные, -- нет никакой.
  • Внутри XMLHTTPRequest нет "огромного буфера", в котором накапливаются данные, прежде чем стать доступными через ResponseText. Однако, XMLHTTPRequest пользуется функциями WinInet, которые буферизируют пришедшие данные, в буфере размером с десяток килобайт. Как результат, работа в "настоящем реальном времени" через XMLHTTPRequest невозможна.
  • Мой хак позволяет выцеплять данные из внутреннего буфера MSXML. Эта функция -- аналог ResponseBody, а не ResponseText, т.к. не происходит должной обработки кодировки ответа. Мне так и нужно; но если кому-то нужен настоящий текст, особенно русский, то придётся извращаться хитрее.
  • Этот код проверен мной с IE6 в WinXP SP2 и Win2000 SP4. В Win98 SE / IE5 он тоже работает, если заменить &HA4 и &HAC на &H58 и &H5C, соответственно. Буду благодарен за тестирование в других конфигурациях.
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 22.07.2006 (Сб) 14:22

Поглядел в утёкшие исходники WinInet, там стоит буфер в 1Кб. Значит, у страха глаза велики :-)


К слову: вот оттуда тесткейсы. Забавненько :-)
Код: Выделить всё
//
// single 100 response
//

#define TEST_HEADER_0   "HTTP/1.1 100 Continue\r\n" \
                        "\r\n"

//
// single 100 header
//

#define TEST_HEADER_1   "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "\r\n"

//
// continue header with moderate amount of data
//

#define TEST_HEADER_2   "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "Content-Length: 128\r\n" \
                        "Content-Type: octet/shmoctet\r\n" \
                        "\r\n" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef"

//
// continue header seen from apache server
//

#define TEST_HEADER_3   "HTTP/1.1 100 Continue\r\n" \
                        "\r\n" \
                        "\n\n\n\n\n"

//
// multiple continue headers, no data
//

#define TEST_HEADER_4   "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "\r\n" \
                        "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "\r\n" \
                        "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "\r\n" \
                        "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "\r\n"

//
// single 100 response, preceeded by preamble and containing a chunked response
//

#define TEST_HEADER_5   "!!!! this is a pre-amble, should be ignored even though it includes HTTP !!!!" \
                        "     " \
                        "HTTP/1.1 100 Go ahead punk, make my day\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "Transfer-Encoding: chunked\r\n" \
                        "\r\n" \
                        "0010 this is the first chunk (16 bytes)\r\n" \
                        "0123456789abcdef" \
                        "\r\n" \
                        "  10; this is the second chunk (16 bytes)\r\n" \
                        "0123456789abcdef" \
                        "\r\n" \
                        "00F3\r\n" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "0123456789abcdef" \
                        "012" \
                        "\r\n" \
                        "0000; the final chunk\r\n" \
                        "\r\n" \
                        "Entity-Header: this is the chunk footer\r\n" \
                        "\r\n"

//
// enpty chunk encoded response with empty footer
//

#define TEST_HEADER_6   "HTTP/1.1 100 Continue\r\n" \
                        "Server: Richard's Test-Case Virtual Server/1.0\r\n" \
                        "Date: Mon, 01 Apr 2000 00:00:01 GMT\r\n" \
                        "Transfer-Encoding: chunked\r\n" \
                        "\r\n" \
                        "0\r\n" \
                        "\r\n" \
                        "\r\n"
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 22.07.2006 (Сб) 16:23

В общем, выходит, что единственный способ качать стрим в реальном времени -- через винсок: даже urlmon/URLOpenStream на самом деле идёт через тот же wininet с его килобайтным буфером... Жалко и обидно.
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 24.07.2006 (Пн) 6:18

Маленько потестировал URLOpenStream. Реально данные приходят кусками по 1.5--4 Кб.
Значит, в первый раз мне правильно показалось.

Никто не знает стандартных способов закачки, не завязанных на wininet? Вон, скажем winhttp -- он через что качает?
Изображение

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 24.07.2006 (Пн) 10:40

1.5--4 Кб. - скорее всего это текущее окно TCP
реального стрима ты нигде не получишь

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 24.07.2006 (Пн) 10:49

Неправда. Я коннекчусь телнетом к самописному скрипту, который отдаёт сто байтов в секунду, и вижу, что они приходят блоками по сто байтов. А потом коннекчусь через wininet, и вижу, что они собираются в килобайтные кучи.
Изображение

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 24.07.2006 (Пн) 11:15

telnet использует свой протокол, к тому же 100 байт как раз укладываются в tcp window frame

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 24.07.2006 (Пн) 11:48

1. Телнет прекрасно работает с любым TCP-сервисом.
2. Если "100 байт как раз укладываются в tcp window frame", то почему же "реального стрима ты нигде не получишь"? Вот, подключаясь без wininet, получаю реальный стрим.
Изображение

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 24.07.2006 (Пн) 12:05

telnet в большинстве случаев прикрывают в целях безопасности, а стрим реалтайм по 100байт - это однако круто :lol:

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 24.07.2006 (Пн) 13:50

Тьфу ты чёрт. Я не о протоколе "telnet", а о виндовой проге под названием "telnet". Никто её не собирался запрещать.
Изображение

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 24.07.2006 (Пн) 13:55

то-то я смотрю, что ты об одном,а я о другом :)

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Сообщение ALX_2002 » 07.05.2007 (Пн) 10:22

Доброго времени суток отцы. Извиняйте неграмотного.

Вопросы назрели. Я вот всегда вот так делал. А тут почитал этот пост и задумался,

Код: Выделить всё
    Dim XmlHttp As Object
    Set XmlHttp = CreateObject("Microsoft.XmlHttp")
    XmlHttp.open "POST", "http://www.ya.ru", False
    XmlHttp.send
   
    Dim ResponseBody() As Byte
   
    ResponseBody = XmlHttp.ResponseBody
   
    Const vbUnicode = 64
   
    Print StrConv(ResponseBody, vbUnicode)


1) Такой код не даёт мне гарантии, что я получу русский текст ?

2) А разве нельзя получать данные кусками, поставив в 206 статус ?

Извиняйте, если глупость спросил :roll:

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 07.05.2007 (Пн) 11:02

ALX_2002 писал(а):2) А разве нельзя получать данные кусками, поставив в 206 статус ?

Извиняйте, если глупость спросил :roll:


Если ты о 206 ака Partial Content то его "поставить" может Web-сервер, отвечая на твой G/P/H-запрос, чем оповещает клиентскую сторону о том, что умеет отдавать только кусок запрашиваемого ресурса.

И ответит он этим заголовком, только если в запросе присутствовал такой заголовок


Код: Выделить всё
Range: 123-456

или
Код: Выделить всё
Range: 123-


Если сервер ответил кодом 206 - клиент должен ожидать что данные, которые в дальнейшем придут с сервера будут действительно являться байтами ресурса, начиная с 123-его, заканчивая 456-байтов включительно (в первом случае), и байтами начиная со 123-его, заканчивая до конца ресурса.

Кстати говоря, это даже не всегда так. Клиент может послать кривой Range, которым сервер при всём желании не сможет ответить.

И правильнее смотреть на заголовки, которые придут уже с сервера вместе с 206-ым кодом, а именно на заголовки Content-Range: xxxxx-yyyyyy/zzzzzzzz

и Accept-Ranges: xxxx(обычно bytes)ххххх


В случае если клиент ответил статусом 200 ОК, то нет никакого смысла смотреть на эти заголовки: клиент должен ожидать, что данные, которые будут приходить от сервера, являются данными запрашиваемого ресурса, начиная от его первого байта, заканчивая последним.

Однако всё вышеописанное, никак не влияет на то, что сервер будут присылать данные кусками (пакетами), поэтому отвечая на твой вопрос

А разве нельзя получать данные кусками, поставив в 206 статус ?


Нельзя, оно и так получается кусками.
Последний раз редактировалось Хакер 07.05.2007 (Пн) 12:16, всего редактировалось 1 раз.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 07.05.2007 (Пн) 12:14

ALX_2002 писал(а):1) Такой код не даёт мне гарантии, что я получу русский текст ?

Если сервер верно отдаёт в заголовках кодировку, значит гарантия будет.
Изображение

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Сообщение ALX_2002 » 07.05.2007 (Пн) 17:04

2 tyomitch + Хакер: Огроменное спасибо дядьки. :) Вроде всё понял. Пойду код править ))) Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 07.05.2007 (Пн) 17:44

2 tyomitch + Хакер


А я сначала не врубился, и думал, чему же равно 2*tyomitch + Хакер.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 08.05.2007 (Вт) 8:14

Хакер писал(а):2*tyomitch + Хакер.

= 11505 :)
Lasciate ogni speranza, voi ch'entrate.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 08.05.2007 (Вт) 9:55

alibek писал(а):
Хакер писал(а):2*tyomitch + Хакер.

= 11505 :)


в каких единицах? :)
Весь мир матрица, а мы в нем потоки байтов!

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 08.05.2007 (Вт) 11:08

Гм... я предположил что в "постингах", но что то несходится на 10 тысяч
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 08.05.2007 (Вт) 11:13

В ID, конечно же, в чём же ещё...
Иными словами, 2*tyomitch + Хакер = inf.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 20.05.2007 (Вс) 20:51

Темыч, в продолжение предыдущих своих воззваний - если сможешь подробно и на английском языке описать, что ты считаешь багом и что ты хотел бы (аргументированно) изменить - напиши мне. Будем поднимать issue.
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 20.05.2007 (Вс) 21:18

А нет больше того бага. Он теперь стал документированной фичей.

В текущей документации написано "Some data has been received. Calling the responseBody and responseText properties at this state to obtain partial results will return an error, because status and response headers are not fully available.", что совпадает с наблюдаемыми фактами.

Раньше там было написано "Some data has been received. You can call responseBody and responseText to get the current partial results."

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

Итак, мои пожелания:
1. (documentation fix) изменить описание на "Some data has been received. However, calling the responseBody and responseText properties at this state to obtain partial results will return an error." (без описания причин), либо придумать причину поправдоподобнее.
2. (feature request) реализовать возможность чтения тела ответа до его полного получения.
Изображение

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 20.05.2007 (Вс) 22:11

Темыч, а можно это подробнее (с аргументами) и на английском (если нет времени, то на русском, но все равно аргументированно) и на email: gaidar.magdanurov@microsoft.com (а то когда я еще посмотрю, а пожелания уже сейчас нужно поднимать :))
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali


Вернуться в Tyomitch

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

    TopList