Linux下gsoap實現webservice功能

藍字爲關鍵字,等號=後面爲關鍵字值。web

1、介紹數組

咱們用的webservice是根據gsoap編譯工具來實現,gSOAP的編譯器可以自動的將用戶定義的本地化的C或C++數據類型轉變爲符合XML語法的數據結構。同時gSOAP可以根據標準化的wsdl(徹底符合wsdl書寫格式)文件來生成本地須要的C或C++源代碼以肯定發送接收XML文件的格式;數據結構

2、使用說明架構

當前咱們用到的gSOAP版本是2.8.3,下面是生成源碼的wsdl文件;若是想要生成C代碼,則在生成源碼時指定-c選項;例如wsdl文件名稱爲host.wsdl,依據如下兩步生成源碼:app

wsdl2h –c –s –o host.h host.wsdl(具體使用能夠查看幫助,依據wsdl文件生成c頭文件)異步

soapcpp2 –c host.h(依據c指定的頭文件生成c源碼)ide

一個簡單host.wsdl文件:(/**/註釋欄爲wsdl說明)函數

------------------------------------------------華麗的分割線-------------------------------------工具

 1 <?xml version="1.0" encoding="UTF-8"?>/*指定版本及編碼格式*/
 2 /*definitions是wsdl根元素,下面一般包含如下元素,即types/ message/ portType/ operation/ binding/ service */
 3 <definitions name="MessageInfo"
 4     xmlns:tns="http://messageinfo.com"
 5     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 6     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
 7     xmlns="http://schemas.xmlsoap.org/wsdl/"
 8     targetNamespace="http://messageinfo.com">
 9 /*types是數據類型定義的元素 其應用主要是schema定義格式類型*/
10 <types>
11  <schema targetNamespace="http://messageinfo.com"
12          xmlns="http://www.w3.org/2001/XMLSchema">
13    <complexType name="StatisticsRequest">
14     <sequence>
15      <element name="request" type="string"/>
16     </sequence>
17    </complexType>
18    <complexType name="StatisticsResponse">
19     <sequence>
20      <element name="AllPaketsnum" type="unsignedLong"/>
21      <element name="WormTypenum" type="unsignedLong"/>
22      <element name="Reverse1" type="string"/>
23     </sequence>
24    </complexType>
25   </schema>
26 </types>
27 /* message描述通訊消息的數據結構的抽象化類型定義 */
28 <message name="GetMessageRequest">
29  <part name="Operateget" type="tns:StatisticsRequest"/>
30 </message>
31 <message name="GetMessageResponse">
32  <part name="Operateput" type="tns:StatisticsResponse"/>
33 </message>
34 /* portType描述服務和服務的方法 */
35 <portType name="MessagePortType">
36  <operation name="GetMessageRepq">
37   <input message="tns:GetMessageRequest"/>
38   <output message="tns:GetMessageResponse"/>
39  </operation>
40 </portType>
41 /* 描述通訊協議,注意rpc document literal encoded各類匹配組合使用*/
42 <binding name="MessageSoapBinding" type="tns:MessagePortType">
43  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
44  <operation name="GetMessageRepq">
45   <soap:operation style="rpc" soapAction=""/>
46    <input>
47     <soap:body use="literal" namespace="http://messageinfo.com"/>
48    </input>
49    <output>
50     <soap:body use="literal" namespace="http://messageinfo.com"/>
51    </output>
52   </operation>
53 </binding>
54 /*service描述webservice訪問點的集合*/
55 <service name="MessageService">
56  <documentation>Stat Message Service Topsec Ips provide</documentation>
57  <port name="MessageSerPort" binding="tns:MessageSoapBinding">
58    <soap:address location="http://localhost:80"/>
59  </port>
60 </service>
61 
62 </definitions>
View Code

 

3、元素介紹性能

關於xml格式問題,參考xml文檔,wsdl具體應用分爲下面幾類:

下面將對每一個元素進行詳細說明:

 1. Definitions

定義了文檔中用到的各個xml元素的namespace縮寫,

也界定了本文檔本身的 targetNamespace="http://www.jsoso.com/wstest",

這意味着其它的XML要引用當前XML中的元素時,要聲明這個namespace。

注意xmlns:tns="http://www.jsoso.com/wstest"這個聲明,它標示了使用tns這個前綴 指向自身的命名空間

1 <definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
2        xmlns:tns:="http://www.jsoso.com/wstest"
3        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
4        xmlns="http://schemas.xmlsoap.org/wsdl/"
5        targetNamesapce="http://www.jsoso.com/wstest"
6        name="Example">
7        ......
8 </definitions>

 2. types

<types>標籤訂義了當前的WSDL文檔用到的數據類型。

要說明的是,爲了最大程度的平臺中立性,WSDL 使用 XML Schema 語法來定義數據類型。

這些數據類型用來定義web service方法的參數和返回值。對於通用的原生數據類型如:

integer , boolean , char , float等,

在W3C的標準文檔http://www.w3.org/2001/XMLSchema中已經作了定義。

這裏咱們要引入的schema定義 schemaLocation="http://localhost:8080/hello?xsd=1"是咱們自定義的對象類型。

(自定義對象類型地址不存在wsdl會怎樣處理?)

1 <types>
2        <xsd:schema>
3               <sxd:import namespace="http://www.jsoso.com/wstest"
4               schemaLocation="http://localhost:8080/hello?xsd=1">
5               </xsd:import>
6        </xsd:schema>
7 </types>

3. message就是用來soap消息的

<message>元素定義了web service函數的參數。

<message>元素中的每一個<part>子元素都和某個參數相符。

輸入參數在<message>元素中定義,與輸出參數相隔離,

輸出參數有本身的<message>元素。

兼做輸入、輸出的參數在輸入輸出的<message>元素中有它們相應的<part>元素。

輸出 <message>元素以"Response"結尾,對Java而言方法得返回值就對應一個輸出的<message>。

每一個<part>元素都有名字和類 型屬性,就像函數的參數有參數名和參數類型。

 1 <message name="sayHello"> 
 2    <part name="person" type="tns:person"></part> 
 3    <part name="arg1" type="xsd:string"></part> 
 4 </message> 
 5 
 6 <message name="sayHelloResponse"> 
 7    <part name="personList" type="tns:personArray"></part> 
 8 </message> 
 9 <message name="HelloException"> 
10    <part name="fault" element="tns:HelloException"></part> 
11 </message>

4. portType

指明服務的接口名稱。

在<operation>元素中,name屬性表示服務方法名,

parameterOrder屬性表示方法的參數順序,

使用空格符分割多個參數,如:「parameterOrder="person arg1」。

<operation>元素的子標籤<input>表示輸入參數說明,它引用<message>標籤中的輸入參數。

<output>表示輸出參數說明,它引用<message>標籤中的輸出參數。

<fault>標籤在Java方法中的特別用來表示異常(其它語言有對應的錯誤處理機制),

它引用<message>標籤中的錯誤參數。

 1 <portType name="Example"> 
 2 
 3    <operation name="toSayHello" parameterOrder="userName"> 
 4      <input message="tns:toSayHello"></input> 
 5      <output message="tns:toSayHelloResponse"></output> 
 6    </operation> 
 7    <operation name="sayHello" parameterOrder="person arg1"> 
 8      <input message="tns:sayHello"></input> 
 9      <output message="tns:sayHelloResponse"></output> 
10      <fault message="tns:HelloException" name="HelloException"></fault> 
11    </operation> 
12 </portType>

5. binding

指定消息傳遞的格式,<binding>標籤是完整描述協議、序列化和編碼的地方,

<types>,<message>和<portType>標籤處理抽象的數據內容,而<binding>標籤是處理數據傳輸的物理實現。

<binding>標籤把前三部分的抽象定義具體化。

style="rpc":消息的展示形式;有兩個值,rpc和content

use="literal":消息應該以什麼樣的形式來傳遞;有兩個值,literal和encodes。但目前都是用literal。

<operation>子標籤將portType中定義的operation同SOAP的請求綁定,

定義了操做名稱soapAction,輸出輸入參數和異常的編碼方式及命名空間。

 1 <binding name="ExamplePortBinding" type="tns:Example"> 
 2    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"></soap:binding> 
 3    <operation name="toSayHello"> 
 4       <soap:operation soapAction="sayHello"></soap:operation> 
 5       <input> 
 6          <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> 
 7       </input> 
 8       <output> 
 9         <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> 
10       </output> 
11    </operation> 
12    <operation name="sayHello"> 
13       <soap:operation soapAction="sayHello"></soap:operation> 
14       <input> 
15          <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> 
16       </input> 
17       <output> 
18          <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> 
19       </output> 
20       <fault name="HelloException"> 
21           <soap:fault name="HelloException" use="literal"></soap:fault> 
22       </fault> 
23    </operation> 
24 </binding>

 

WSDL 綁定樣式由兩個屬性組合而成:style、use;style能夠是RPC/Document,use能夠是Encoded/Literal;下面解釋下這4個名詞的意思:

RPC 樣式

RPC樣式指定<soap:body> 元素包含一個將被調用的web方法的名稱的元素(wrapper element(封裝元素))。這個元素依次爲該方法的每一個參數還有返回值做了記錄。

Document 樣式

若是是document 樣式,就沒有像在RPC樣式中的wrapper元素。轉而代之的是消息片段直接出如今<soap:body>元素之下。沒有任何SOAP格式化規則規定<soap:body>元素下能包含什麼;它包含的是一個發送者和接收者都達成一致的XML文檔。

Encoded 編碼

若是use的值是」encoded」, 則每一個消息片斷將使用類型屬性來引用抽象類型。經過應用由 encodingStyle 屬性所指定的編碼樣式,可以使用這些抽象類型生成具體的消息。最經常使用到的SOAP編碼樣式是在SOAP1.1中定義的一組序列化規則,它說明了對象、結構、數組和圖形對象應該如何序列化。一般,在應用程序中使用SOAP編碼着重於遠程進程調用和之後適合使用RPC消息樣式。

Literal 文字

若是use 的值是」Literal」, 則每一個片斷使用 element 屬性(對於簡單片斷)或 type 屬性(對於複合片斷)來引用具體架構,例如,數據根據指定的架構來序列化,這架構一般使用W3C XML架構來表述。

根據不一樣的組合,造成了四種綁定模型;另外,還有一種用Document模擬RPC樣式的包裝組合也很常見;

1.RPC/Encoded

2.RPC/Literal

3.Document/Encoded

4.Document/Literal

5.Document/Literal Wrapped

對於以上5種組合方式,因爲Document/Encoded不被現有平臺所支持,在實際中應用不多,因此這裏就暫時不討論該種組合;對於剩下的4種組合,咱們結合一個表格和實例來對比下各自的優劣狀況;

Binding Type  Advantage/DisAdvantage

RPC/Encoded 優勢:

  1.WSDL文件的定義遵循直觀和衆所周知的遠程進程調用的溝通模式。

  2.操做名顯示在消息中,所以接收者很容易就把消息分派給它的實現。

  3.若是你正在你的服務中使用數據圖形或者多態,這是唯一能使用的樣式。

缺點:

  1.SOAP消息包含的類型編碼信息就如xsi:type="xsd:int",這些就是一種開銷。

  2.一般驗證SOAP消息是很困難的,由於在WSDL Shcema中沒有描述。

  3.RPC樣式引發了一種在服務提供者和客戶之間的緊密耦合,任何對接口的更改都會致使服務和客戶間聯繫的中斷。

  4.不被WSI一致性標準所支持。RPC/

Literal 優勢:

  1.WSDL定義仍然像RPC/Encoded樣式同樣簡單直接。

  2.操做名仍然出如今SOAP消息中。

  3.把類型編碼從消息中排除了,所以提高了吞吐性能。

缺點:

  1.服務和客戶之間仍然有緊密耦合。

  2.仍然難以用SOAP消息來驗證傳輸的數據。

  3.它也不被WSI一致性標準所支持。

Document/Litaral   優勢:

  1.在SOAP消息中沒有類型編碼信息。

  2.你總能用任何XML驗證器來驗證消息,在soap體中任何東西都在schema中有定義。

  3.使用document樣式,規則不是那麼嚴格,還有對XML Schema進行加強和更改時不會破壞接口。

  4.若是使用某特殊序列進行多進程調用,Document 樣式能夠保持應用程序的狀態。

  5.Document樣式更加適合異步處理。

  6.許多document-messaging服務可以選擇文檔的DOM和SAX 兩種處理方式的其中一種,結果就是能最小化在內存中的處理。

缺點:

  1.WSDL定義變得更加複雜。

  2.在SOAP消息中的操做名沒有了,沒有了名稱,把消息分派給它的實現方法就變得困難或不可能了。

Document/Literal

Wrapped  優勢:

  1.包含了全部Document/Literal樣式的優勢。

  2.操做名出如今SOAP消息中。

缺點:

  1.即便WSDL定義變得更加複雜,但仍然有很多缺點。

  2.若是你在web服務中重載了操做,你就不能使用該樣式。

6. service

service是一套<port>元素。

在一一對應形式下,每一個<port>元素都和一個location關聯。

若是同一個<binding>有多個<port>元素與之關聯,

可使用額外的URL地址做爲替換。

一個WSDL文檔中能夠有多個<service>元素,

並且多個<service>元素十分有用,其中之一就是能夠根據目標URL來組織端口。

在一個 WSDL文檔中,<service>的name屬性用來區分不一樣的service。

在同一個service中,不一樣端口,使用端口的"name"屬性區 分。

1 <service name="Example"> 
2    <port name="ExamplePort" binding="tns:ExamplePortBinding"> 
3       <soap:address location="http://localhost:8080/hello"></soap:address> 
4    </port> 
5 </service>

 

4、說明

這裏編寫webservice.c文件能夠將須要的代碼程序生成so(動態庫),方便隨時調用(具體使用說明參考gsoap)

 1 # Makefile for make libwebservice.so
 2 
 3 DIRS =
 4 SHARE = -shared -lc
 5 USER_LIBS = -lssl -ldl -lcrypto
 6 MODULES = libwebservice.so
 7 MODULES_OBJS = soapC.o soapServer.o stdsoap2.o webservice.o
 8 
 9 CFLAGS = -Wall -DWITH_OPENSSL
10 
11 all: $(MODULES)
12 
13 $(MODULES): $(MODULES_OBJS)
14         cc $(USER_LIBS) $(CFLAGS) ${SHARE} -o ${MODULES} $^
15         strip ${MODULES}
16 
17 clean:
18         rm *.o *.a *.so -rf
19         for filename in $(DIRS); do \
20                 ( cd $$filename;  $(MAKE) $@ ); \
21         done

 

瞭解了整個結構,對傳輸類型及方式能夠很好的把控,也能夠將整個結構體進行傳輸及使用。

相關文章
相關標籤/搜索