gSOAP 源碼分析(一)
邵盛松 2012-5-22
一 SOAP消息結構
SOAP消息包括以下元素
必需的 Envelope 元素,可把此 XML 文檔標識為一條 SOAP 消息,XML文件的頂層元素,代表該文件為SOAP消息
可選的 Header 元素,包含頭部信息
必需的 Body 元素,包含所有的調用和響應信息
可選的 Fault 元素,提供有關在處理此消息所發生錯誤的信息
可選的Attachment,主要用於傳遞附件,擴展的SOAP消息
Envelope是SOAP消息中的根節點,是SOAP消息中必需的部分;Header是SOAP消息中可選部分,如果SOAP消息中含有它,那麼它一定要是soap:Envelope>中的第一個元素節點;Body是SOAP中必需部分,如果SOAP消息中沒Header,那麼Body必須是SOAP中第一個元素節點。
在默認生成的代碼中關於Header 元素定義
/* SOAP Header: */
struct SOAP_ENV__Header
{
#ifdef WITH_NOEMPTYSTRUCT
private:
char dummy; /* dummy member to enable compilation */
#endif
};
下圖為SOAP消息的結構
<faultstring>這裡的錯誤是為人設定的,讓人讀懂,而不是為程序處理設定的。
<faultactor>有關是誰引發故障的信息
<detail>Body元素中的內容不能被成功地處理的時候,它就出現了。
代碼中fault結構體如下
struct SOAP_ENV__Fault
{
public:
char *faultcode; /* optional element of type xsd:QName */
char *faultstring; /* optional element of type xsd:string */
char *faultactor; /* optional element of type xsd:string */
struct SOAP_ENV__Detail *detail; /* optional element of type SOAP-ENV:Detail */
struct SOAP_ENV__Code *SOAP_ENV__Code; /* optional element of type SOAP-ENV:Code */
struct SOAP_ENV__Reason *SOAP_ENV__Reason; /* optional element of type SOAP-ENV:Reason */
char *SOAP_ENV__Node; /* optional element of type xsd:string */
char *SOAP_ENV__Role; /* optional element of type xsd:string */
struct SOAP_ENV__Detail *SOAP_ENV__Detail; /* optional element of type SOAP-ENV:Detail */
};
Fault是Body的一個子元素主要用於用於報告錯誤。
SOAP命名空間
SOAP_NMAC struct Namespace namespaces[] =
{
{"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
{"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
{"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
{"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
{"ns", "urn:calc", NULL, NULL},
{NULL, NULL, NULL, NULL}
};
這裡的URL並不是指向文件,而只是一個名字。如果一個SOAP應用程序接收了一個消息,而該消息的SOAP Envelope元素使用和上述不同的名稱空間,則該應用程序就將其視為版本錯誤並忽略該消息。
二 gSOAP Keep-Alive和超時管理
gSOAP是綁定Http協議來對xml數據進行傳輸,一個SOAP請求實際上就是一個HTTP POST請求。
消息從發送方到接受方方是單向傳送,即以請求/應答的方式實現的。這也就是為什麼生成的xml文件都是req,res成對出現的
gSOAP運行環境實例是一個struct soap類型的變量,struct SOAP_STD_API soap
。
gSOAP支持HTTP Keep-Alive,生成代碼中默認沒有使用Keep-Alive
calcService_init(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
如果參數更改SOAP_IO_KEEPALIVE將使用Keep-Alive,默認最大連接100
以下代碼在soap結構體中
short tcp_keep_alive; /* enable SO_KEEPALIVE */
unsigned int tcp_keep_idle; /* set TCP_KEEPIDLE */
unsigned int tcp_keep_intvl; /* set TCP_KEEPINTVL */
unsigned int tcp_keep_cnt; /* set TCP_KEEPCNT */
unsigned int max_keep_alive; /* maximum keep-alive session (default=100) */
TCP_KEEPIDLE 空閒多久開始發送keepalive包
TCP_KEEPCNT 總共發送多少個
TCP_KEEPINTVL 每兩個keepalive包的發送時間間隔
這種非阻塞管理需要設置超時時間
接收超時時間
發送超時時間
連接超時時間
接受請求超時時間
代碼如下,這也是soap結構體的一部分
int recv_timeout;/* when > 0, gives socket recv timeout in seconds, < 0 in usec */
int send_timeout;/* when > 0, gives socket send timeout in seconds, < 0 in usec */
int connect_timeout;/* when > 0, gives socket connect() timeout in seconds, < 0 in usec */
int accept_timeout;/* when > 0, gives socket accept() timeout in seconds, < 0 in usec */
正值以秒為單位。負值以微秒為單位。
三 提高速度技巧
1 通過更改在stdsoap2.h文件中SOAP_BUFLEN宏,增加緩存大小
2 如果客戶端需要多次連接相同的服務器,那麼客戶端使用HTTP keep-alive。服務端也要支持HTTP keep-alive,這樣能夠最大的增強服務端和客戶端的性能。
3 使用HTTP分塊傳輸
4 不要使用gzip壓縮
摘自 flyfish1986的專欄