Конференция "Сети" » XMLHTTP [D7, WinXP]
 
  • dima_q (30.06.08 13:13) [0]
    Здравствуйте Мастера!
    Есть COM библиотека служащая для общения с сервером. Общения происходит посредством xml по http. Для непосредственной связи используется объект XMLHTTP. Вопрос: Для работы с сервером, в моей либе создается отдельный поток. В потоке осуществляется вход в апартмент:
    CoInitializeEx(nil, COINIT_APARTMENTTHREADED)

    . После создания объекта c и присвоения всех свойств, вызывается метод
    XMLHTTP.send()

    . Так вот при использовании потоковой модели STA(COINIT_APARTMENTTHREADED) запрос на сервер не идет, все остается висеть навечно. А при использовании MTA все благополучно проходит. Сам сервер XMLHTTP в реестре помечен как Appartment. Подскажите в чем может быть проблема. Почему при STA не вознивает никаких ошибок, но запрос не происходит? P.S.: использовать MTA нет возможности, из-за дальнейших проблем с клиентами моей либы.
  • Сергей М. © (30.06.08 13:29) [1]
    А при CoInitialize(nil) работает ?
  • dima_q (30.06.08 13:35) [2]

    > Сергей М. ©   (30.06.08 13:29) [1]
    > А при CoInitialize(nil) работает ?

    Нет не работает. CoInitialize(nil) идентичен CoInitializeEx(nil, COINIT_APARTMENTTHREADED), это его сокращенный вызов.
  • dima_q (30.06.08 13:37) [3]
    Вся проблема в том, что при работе с CoInitializeEx(nil, COINIT_APARTMENTTHREADED) нет никаких ошибок. Просто тупо не посылает запрос.
  • Сергей М. © (30.06.08 16:37) [4]

    >  тупо не посылает запрос.


    С чего ты взял, что "не посылает" ?

    А если и не посылает, то что значит "все .. висеть" ?

    ты исключения обрабатываешь ?
  • dima_q (30.06.08 17:51) [5]
    Исключения обрабатываю, их нет. Висит, в смысле на сервере, он тоже мой, стоит бряка, но запрос не доходит до него.
  • dima_q (30.06.08 17:53) [6]
    И статус (XMLHTTP.readyStatus) не изменяется никогда, он всегда 1. Хотя сервер доступен.
  • clickmaker © (30.06.08 17:59) [7]
    onreadystatechange используешь или синхронно?
  • dima_q (30.06.08 18:09) [8]

    > clickmaker ©   (30.06.08 17:59) [7]
    > onreadystatechange используешь или синхронно?

    Не использую. Просто в цикле проверяю XMLHTTP.readyState.
  • clickmaker © (30.06.08 18:16) [9]
    погодь... насколько я знаю, там либо синхронно, тогда send не вернет, пока не выполнится, либо асинхронно, тогда надо вешать onreadystatechange
    попробуй второй вариант
  • dima_q (30.06.08 18:30) [10]
    Пробовал при асинхронном запросе вешать onreadystatechange, не происходит события. Сейчас попробую, что скажет синхронный.
  • dima_q (30.06.08 19:27) [11]
    В синхронном режиме сенд проходит нормально, не знаю что делать...
  • Сергей М. © (30.06.08 19:47) [12]

    > В синхронном режиме сенд проходит нормально


    Отсюда и вывод: threading model тут совершенно ни причем.

    Похоже что XMLHTTP в асинхр.режиме заточен на нотификацию посредством оконных сообщений. И, поскольку в теле цикла ты не предпринимаешь никаких телодвижений по выборке/диспетчеризации оных, ожидать onreadystatechange или изменение readyState придется до второго пришествия.
  • dima_q (01.07.08 09:35) [13]

    > Сергей М. ©

    Буду копать в сторону цикла обработки сообщений в потоке. Мот я просто не так добавлял его, попробую еще раз, огромное спасибо!
  • Сергей М. © (01.07.08 16:47) [14]

    > Мот я просто не так добавлял его


    Кого ?!
  • dima_q (02.07.08 09:42) [15]

    > Кого ?!

    Цикл обработки сообщений. Попробовал, не работает все равно. Незнаю, что делать:(
  • Сергей М. © (02.07.08 10:16) [16]

    > Незнаю, что делать


    Ну как что ?
    Трясти бубен, если код своего цикла показывать не желаешь)
  • dima_q (02.07.08 10:26) [17]

    > Трясти бубен, если код своего цикла показывать не желаешь)

     Думаю бубен вряд ли поможет, а код,  вот он:

       TXMLHTTPThread = class(TThread)
       private
           m_xmlHTTP30 : MSXML3.TXMLHTTP30;
           m_xmlHTTP40 : MSXML5.TXMLHTTP40;
           m_xmlHTTP50 : MSXML5.TXMLHTTP50;
         ...

           procedure ParseResponse();
           function  CheckOfTimeout(xmlHTTP : TXMLHTTP) : integer;// 0 - aborted, 1 - timed out, 4 - successful;
       public
           AlwaysSaveToFile : boolean;
           constructor Create(async : boolean; url: string; sFileName: string = ''; stmPost: TIdMultipartFormDataStream = nil);
           destructor Destroy(); override;
           procedure Execute(); override;
           ...
       end;

    ...
       function TXMLHTTPThread.CheckOfTimeout(xmlHTTP: TXMLHTTP): integer;
       var lastState, diff : integer;
           ticks : cardinal;
           rMsg : TMsg;
       const ts : array [0..3] of integer = (60*1000,60*1000,10*60*1000,10*60*1000);
       begin
           Result := 4;
           ticks := GetTickCount();
           lastState := xmlHTTP.readyState;
           while (lastState <> 4) do
           begin
               while (GetMessage (rMsg,0,0,0)) do DispatchMessage (rMsg);
               Sleep(50);
               if (GetTickCount() - ticks > ts[lastState]) then
               begin
                   xmlHTTP.abort();
                   Result := 1;
                   Exit;
               end;
               if Terminated then
               begin
                   xmlHTTP.abort();
                   Result := 0;
                   Exit;
               end;
               if (xmlHTTP.readyState > lastState) then
               begin
                  ticks := GetTickCount();
                  lastState := xmlHTTP.readyState;
               end;
           end;
       end;

       constructor TXMLHTTPThread.Create(async : boolean; url: string; sFileName: string = ''; stmPost: TIdMultipartFormDataStream = nil);
       begin
           inherited Create(true);
           m_xmlHTTP30 := nil;
           m_xmlHTTP40 := nil;
           m_xmlHTTP50 := nil;
           ...
       end;

       destructor TXMLHTTPThread.Destroy();
       begin
          ...
       end;

       procedure TXMLHTTPThread.Execute();
       var stmString : TStringStream;
           i, rs : integer;
           s : string;
       begin
           CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
           //COINIT_MULTITHREADED
           //COINIT_APARTMENTTHREADED

           case (XMLVersion) of
               xml30: m_xmlHTTP30 := MSXML3.TXMLHTTP30.Create(nil);
               xml40: m_xmlHTTP40 := MSXML5.TXMLHTTP40.Create(nil);
               xml50: m_xmlHTTP50 := MSXML5.TXMLHTTP50.Create(nil);
               xmlUnknown :
               begin
                   m_error := 'Cannot access network : MSXML version 3.0 or higher is required';
                   m_completed := true;
                   CoUninitialize();
               end;
           end;

           try
               try
                   ...

                   if (XMLVersion = xml30) then
                   begin
                       if (m_stmPost <> nil) then m_xmlHTTP30.send(m_postdata)
                       else m_xmlHTTP30.send();
                       if m_async then
                           case CheckOfTimeout(TXMLHTTP(m_xmlHTTP30)) of
                               0: begin m_error := 'aborted'; Exit; end;
                               1: begin m_error := 'timed out'; Exit; end;
                           end;
                   end else if (XMLVersion = xml40) then
                   begin
                       if (m_stmPost <> nil) then m_xmlHTTP40.send(m_postdata)
                       else m_xmlHTTP40.send();
                       if m_async then
                       begin
                           case CheckOfTimeout(TXMLHTTP(m_xmlHTTP40)) of
                               0: begin m_error := 'aborted'; Exit; end;
                               1: begin m_error := 'timed out'; Exit; end;
                           end;
                       end;
                   end else
                   begin
                       if (m_stmPost <> nil) then m_xmlHTTP50.send(m_postdata)
                       else m_xmlHTTP50.send();
                       if m_async then
                       begin
                           case CheckOfTimeout(TXMLHTTP(m_xmlHTTP50)) of
                               0: begin m_error := 'aborted'; Exit; end;
                               1: begin m_error := 'timed out'; Exit; end;
                           end;
                       end;
                   end;

                   if (XMLVersion = xml30) then
                       rs := m_xmlHTTP30.readyState
                   else if (XMLVersion = xml40) then
                       rs := m_xmlHTTP40.readyState
                   else
                       rs := m_xmlHTTP50.readyState;

                   if (rs >= 2) then // LOADED, STATUS is available
                   begin
                       if (XMLVersion = xml30) then
                           m_respCode := m_xmlHTTP30.status
                       else if (XMLVersion = xml40) then
                           m_respCode := m_xmlHTTP40.status
                       else
                           m_respCode := m_xmlHTTP50.status;
                       try
                           if (m_respCode >= 400) then
                           begin
                               m_error := 'ServerXMLHTTP returned an error : ';
                               if (XMLVersion = xml30) then
                                   s := m_xmlHTTP30.statusText
                               else if (XMLVersion = xml40) then
                                   s := m_xmlHTTP40.statusText
                               else
                                   s := m_xmlHTTP50.statusText;

                               if (Length(s) > 0) then m_error := m_error + s
                               else m_error := m_error + ResponseCodeText(m_respCode);
                           end;
                       except end;
                   end;

                   if (rs = 4) then ParseResponse();

               except
                   on ex : Exception do
                   begin
                       m_error := {'ServerXMLHTTP has returned an error: ' +} ex.Message;
                   end;
               end;
           finally
               m_completed := true;
               if (XMLVersion = xml30) then
                   FreeAndNil(m_xmlHTTP30)
               else if (XMLVersion = xml40) then
                   FreeAndNil(m_xmlHTTP40)
               else
                   FreeAndNil(m_xmlHTTP50);
               CoUninitialize();
           end;
       end;
    end.
  • Сергей М. © (02.07.08 11:27) [18]
    Чудесно.

    А где в этом коде собственно установка асинхронного режима работы компонента ?

    Или это дифолтный режим ?
  • dima_q (02.07.08 11:41) [19]

    > А где в этом коде собственно установка асинхронного режима
    > работы компонента ?

    Нет не дефолтный. Он передается параметром в функцию Open:
    m_xmlHTTP50.open('POST', m_url, m_async);
    я просто удалил куски кода(где ...).
  • Сергей М. © (02.07.08 11:51) [20]
    Ну тогда твой цикл ожидания/выборки/диспетчеризации сообщений никуда не годится - "вис" происходит на GetMessage, когда из очереди выбраны и диспетчеризованы все имеющиеся там сообщения (т.е. очередь пуста).
  • dima_q (02.07.08 12:14) [21]

    > Ну тогда твой цикл ожидания/выборки/диспетчеризации сообщений
    > никуда не годится - "вис" происходит на GetMessage, когда
    > из очереди выбраны и диспетчеризованы все имеющиеся там
    > сообщения (т.е. очередь пуста).

    Подскажите выход... пожалуйсто:) Каим должен быть цикл выборки сообщений, можно пример?
  • Сергей М. © (02.07.08 13:17) [22]
    Без учета таймаута примерно таким:

    while not Terminated and (lastState <> 4) do
    begin
     if PeekMessage(rMsg,0,0,0, PM_REMOVE) then
       DispatchMessage (rMsg)  
     else
       Sleep(0);
    end;
  • dima_q (02.07.08 13:32) [23]
    Уважаемый
    > Сергей М. ©
    огромнейшее, просто громадное Вам человеческое спасибо!!! Все работает... Вопрос закрыт.
  • igor_r © (11.08.08 02:06) [24]
    Всем доброго времени суток.

    У меня задача схожая с dima_q, и отличается лишь тем, что данные передаются через SSL. Приложение пишу на ВСВ. Установил OpenSSL, подвязал сертификат. Если функция send пустая, идет обращение на сервер, запрашивается сертификат, получаю ответ с сервера. А если заполняю send данными получаю пустое окно ответа и сертификат не запрашивается. Скорее всего с передаваемыми данными что-то не так. Может что-то посоветуете.

    Игорь
  • Сергей М. © (11.08.08 08:43) [25]

    > Если функция send пустая


    Как это "пустая" ?


    > заполняю send данными


    Как можно "заполнить функцию данными" ?

    Ерунда какая-то ..
  • igor_r © (11.08.08 10:49) [26]
    Функция send может быть как с параметром так и без него: send() или
    send(data)

    Игорь.
  • Сергей М. © (11.08.08 12:21) [27]
    И что ?

    Вызов функции, с параметром или без, - это просто вызов функции, не более того.

    Причем здесь какое-то там ее "наполнение" ?
  • igor_r © (11.08.08 12:53) [28]
    Сергей! Не придирайся к словам. Давай по существу проблемы...
  • Сергей М. © (11.08.08 13:07) [29]
    Проблема в тебе.
    Я понятия не имею, что у тебя творится в этой самой send
  • igor_r © (11.08.08 13:30) [30]
    Спасибо за теплые слова.
    Передаю на сервер через SSL следующее:
    Variant bstr;
    bstr.VType=VT_BSTR;
    SysFreeString(bstr.bstrVal);
    bstr.bstrVal=SysAllocString(L"<?xml\ version='1.0'\ encoding='WINDOWS-1251'?><request><tpnum>-1</tpnum></request>");
    hRes=pXMLHTTP->send(bstr);
    На локальном HTTP сервере передача информации проходит успешно.
  • Сергей М. © (11.08.08 13:47) [31]

    > На локальном HTTP сервере передача информации проходит успешно


    Чудесно.

    А какое отношение это имеет к STA и MTA ?
  • igor_r © (11.08.08 14:12) [32]
    Вопрос связан с передачей информации через SSL методом XMLHTTP.send(data).
  • Сергей М. © (11.08.08 14:14) [33]

    > igor_r ©   (11.08.08 14:12) [32]


    А у автора вопрос был совершенно о другом.
  • igor_r © (11.08.08 14:24) [34]
    Но решаемые задачи схожие. Форум практически единственный который затронул эту тему. Да и автор вопроса ковырнул эту тему глубоко...
  • Сергей М. © (11.08.08 14:48) [35]

    > автор вопроса ковырнул эту тему глубоко


    А ты внимательно читал ветку, перед тем как сделать вывод о якобы "схожести" ?
  • igor_r © (11.08.08 14:52) [36]
    Тема открытая автором XMLHTTP.
    Сергей, тебе что поговорить не с кем? Лучше бы толковое что написал.
    Считаю вопрос закрытым.
  • Сергей М. © (11.08.08 15:01) [37]

    > Тема открытая автором XMLHTTP


    А дальше идет речь о конкретностях - об особенностях функционирования компонента в тех или иных условиях и режимах.

    Ты же не сподобился даже изложить свои условия и режим эксплуатации компонента !

    Какого же лешего ты ожидаешь услышать в ответ что-то "толковое" ?

    Вот изволь сначала привести эти немаловажные подробности, потом и разговор будет предметным.
 
Конференция "Сети" » XMLHTTP [D7, WinXP]
Есть новые Нет новых   [134432   +19][b:0][p:0.001]