Для удобства сразу включим режим отладки:
Например, есть Proxy класс (тот в который включается #include "soapH.h").
Например, есть Proxy класс (тот в который включается #include "soapH.h").
Через экземпляр этого класса выполняется запрос к веб-сервису. Объявление метода для выполнения запроса выглядит в заголовочном файле примерно так:
virtual int myOperation(ns__myRequest *ns__myRequest_ , ns__myResponse *ns__myResponse_) { return this->myOperation(NULL , NULL , ns__myRequest_ , ns__myResponse_); }
Как видно этот метод является оберткой для другого метода, объявление которого в том же заголовочном файле выглядит следующим образом:
virtual int myOperation(const char *endpoint , const char *soap_action , ns__myRequest *ns__myRequest_ , ns__myResponse *ns__myResponse_);
Далее рассмотрим уже определение этого метода в .cpp файле Proxy класса. Начальная часть метода:
int Proxy::myOperation(const char *endpoint , const char *soap_action , ns__myRequest *ns__myRequest_ , ns__myResponse *ns__myResponse_) { struct soap *soap = this->soap; // [1] struct __ns__myOperation soap_tmp___ns__myOperation; // [2] if (endpoint) // [3] soap_endpoint = endpoint; if (soap_endpoint == NULL) soap_endpoint = "http://example.com:8080/web/service/"; if (soap_action == NULL) soap_action = ""; // [8] soap_begin(soap); // [9] soap->encodingStyle = NULL; soap_tmp___ns__myOperation.ns__myRequest_ = ns__myRequest_; // [11] soap_serializeheader(soap); [12] soap_serialize___ns__myOperation(soap, &soap_tmp___ns__myOperation); // [13] if (soap_begin_count(soap)) // [14] return soap->error; if (soap->mode & SOAP_IO_LENGTH) { if (soap_envelope_begin_out(soap) || soap_putheader(soap) || soap_body_begin_out(soap) || soap_put___ns__myOperation(soap, &soap_tmp___ns__myOperation, "-ns:myOperation", NULL) || soap_body_end_out(soap) || soap_envelope_end_out(soap)) return soap->error; }
[1] Указатель на структуру типа soap, это структура является основной, далее большинство методов будут работать именно с ней.
[2] Создается экземпляр структуры __ns__myOperation, которая просто содержит в себе один указатель на ns__myRequest_ и всё. Назначение указателю происходит на [11].
[3-8] Инициализация точки назначения запросов soap_endpoint и переменной soap_action. Обратите внимание, что значения для этих переменных берутся из аргументов функции.
[9] Инициализация soap структуры (stdsoap2.cpp):
/******************************************************************************/ #ifndef PALM_2 SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap *soap) { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); if (!soap->keep_alive) { soap->buflen = 0; soap->bufidx = 0; } soap->null = 0; soap->position = 0; soap->encoding = 0; soap->mustUnderstand = 0; soap->mode = 0; soap->ns = 0; soap->part = SOAP_END; soap->event = 0; soap->evlev = 0; soap->alloced = 0; soap->count = 0; soap->length = 0; soap->cdata = 0; soap->error = SOAP_OK; soap->peeked = 0; soap->ahead = 0; soap->idnum = 0; soap->level = 0; soap->endpoint[0] = '\0'; soap->encodingStyle = SOAP_STR_EOS; #ifndef WITH_LEANER soap->dime.chunksize = 0; soap->dime.buflen = 0; #endif soap_free_temp(soap); } #endif /******************************************************************************/
[12-13] Сериализация заголовка и запроса.
Остальная часть метода:
if (soap_end_count(soap)) // [26] return soap->error; if (soap_connect(soap, soap_url(soap, soap_endpoint, NULL), soap_action) || soap_envelope_begin_out(soap) || soap_putheader(soap) || soap_body_begin_out(soap) || soap_put___ns__myOperation(soap, &soap_tmp___ns__myOperation, "-ns:myOperation", NULL) || soap_body_end_out(soap) || soap_envelope_end_out(soap) || soap_end_send(soap)) // [27] return soap_closesock(soap); if (!ns__myResponse_) return soap_closesock(soap); ns__myResponse_->soap_default(soap); if (soap_begin_recv(soap) || soap_envelope_begin_in(soap) || soap_recv_header(soap) || soap_body_begin_in(soap)) return soap_closesock(soap); ns__myResponse_->soap_get(soap, "ns:myResponse", "ns:myResponse"); if (soap->error) return soap_recv_fault(soap, 0); if (soap_body_end_in(soap) || soap_envelope_end_in(soap) || soap_end_recv(soap)) return soap_closesock(soap); return soap_closesock(soap); }
[14-26] Подсчет разных величин.
[27]
-> В этом условии (имеется весь if) впервые устанавливается сетевое соединение через сокеты.
--> Отправка XML запроса по HTTP проходит в функции soap_end_send, до этого работа идет по TCP.
---> soap_end_send функция вызывает другую функцию soap_end_send_flush.
----> soap_end_send_flush функция вызывает первую встречу функцию soap_flush.
-----> soap_flush функция вызывает последнюю встречу функцию soap_flush_raw. Функция soap_flush_raw получает на вход аргументы: n - это размер запроса в байтах, s - HTTP-запрос.
------> soap_flush_raw вызывает soap->fsend(soap, s, n);
stdsoap2.cpp |
--