服務流程圖
代碼請參看gSOAP 2.8.14 User Guide 中的7.2.4 How to Create a Multi-Threaded Stand-Alone Service.
listen : 監聽soap_accept方法,返回一個SOAP_SOCKET,然后交SOAP_SOCKET添加到隊列,并發送一個信號通知process(處理線程)處理.
process(處理線程)啟動后立即阻塞等待信號,收到信號后才執行相應的任務(soap_serve
),執行任務后繼續阻塞等待信號.注意:soap_serve方法如果客戶端提交的xml文檔格式不正確或其它數據(惡意攻擊)時會一直阻塞到下一個請求,導到服務器性能嚴重下降,客戶端無法收到數據一直等待的情況,因此在初始化處理線程的soap成功后,應該立即設置處理線程soap的超時時間,單位為秒:
soap_thr[i] = soap_copy(&soap);//在這一行示例代碼后一加下面三行代碼
soap_thr[i] ->send_timeout = 1;
soap_thr[i] ->recv_timeout = 1;
soap_set_mode(soap_thr[i], SOAP_C_UTFSTRING); /*設置采用UTF-8字符編碼*/
例如下列的一個請求就會導致soap_serve阻塞(ns2:login節點沒有閉合)
因為mod_gsoap附加到web服務器的方式問題比較多,iis比較復雜, apache只支持C開發模式,所以gsoap做為一個單獨的服務運行,通過代理調用服務.iis可用其它插件或自己編寫一個代理類,apache直接修改httpd.conf配置代理.
gsoap內存管理
盡量采用soap_malloc(用法和malloc一樣)方法分析內存, soap_malloc無需釋放內存,在gsoap內部采用鏈表的方式管理分配的內存,在執行soap_destroy(tsoap); soap_end(tsoap)后會自動回收內存.
自動回收內存的前提是保證你自己編寫的方法能正確運行完成,否則還是會導致內存泄露.
gsoap輸出
為提升服務性能,減少數據傳輸量,建議所有輸出都采用字符方式的xml(UTF-8), 不要采用結構或對象輸出(輸入可以),采用結構或對象輸出優點是在客戶端無需解析,自動生成相關對象和結構,但是會導致服務性能下降和傳輸的數量增大.例如:
int ns2__login(xsd__string username,xsd__string password,xsd__string &rsp);
rsp為字符串格式的xml,在客戶端需要解析后方可使用.我自己定義的rsp有三種輸出格式,所有節點名稱都大寫,所有屬性名稱都小寫,節點之間無換行,客戶端按下面的三種規則編寫解析器即可.
第一種為服務器異常消息
第二種為正常輸入
更多ROW.......................................
更多ROWS.......................................
第三種為字段描述信息
更多字段描述信息.......................................
更多FIELDS.......................................
type,size, required均為數字,type可以自己定義,解析時按自定義規則轉換數據即可,size為字段大小, required值一般為0和1,為0表示不是必填,否則為必填項.
字符轉換為保證可移值性,可采用iconv轉換,windows和linux均支持,windows需要自己下載LibIconv for Windows - GnuWin32庫.只需要記住UTF-8單個字符最多使用4字節存儲即可.轉換時一次性分配 tcslen(szBuffer) * 4 + sizeof(TCHAR)大小的內存.