天天看點

[WSE]Web Service與Windows Service通過WSE2.0建立訂閱/釋出關系[更新版]

編寫者:鄭昀@ultrapower 

編寫日期:2005-04-13

修改日期:2005-05

<b>目的:</b><b></b>

我們建立這種互動關系的目的是,在web service和windows service(或者其他windows應用)之間建立起一種穩固的可擴充的不受地域限制的互動關系。 

這種互動關系的優點是:

<b>完全異步:</b><b></b>

web service和windows service/windows form都可以實作互動的異步性,也就說,二者的互動完全是通過delegate和wse2.0消息機制實作的,彼此依賴性降低,web service可以像一個二傳手,不斷地将使用者發起的請求路由到背景服務,web service不用和windows service之間保持長連接配接;windows service處理請求完畢,就發送soap消息給web service的http endpoint。

你甚至可以在使用wse2.0的msmq transport來替代http/tcp channel作為底層通信。

<b>可擴充:</b><b></b>

這種soap消息很容易定制和擴充新的標頭定義。

<b>可分布:</b><b></b>

由于webservice的http endpoint位址可以随着web service發消息給背景服務,是以webservice部署在哪裡無關緊要,都可以和windows service保持互動。webservice是通過wse2.0中的<b>ws_addressing</b>機制把消息路由給windows service的,是以二者可以部署到不同的機器上,隻需要改變webservice的配置檔案即可,背景服務能夠根據傳過來的soap包中的replyto字段獲知應該如何給哪裡的http終結點回傳消息。

由于web service的執行身份受限,是以我們無法直接讓web service申請作為一個soapreceiver,而是通過下面的web.config定義來制定本虛拟目錄的.ashx終結點,進而通過<b>ws_addressing</b>和<b>ws_messaging</b>機制來完成<b>web service</b>與<b>windows service</b>之間的訂閱/釋出機制。

在 asp.net 中,可以通過ihttphandler,将 soapreceiver 與 http 信道進行內建。如果檢視一下soapreceiver 的定義,您會注意到它實作了 ihttphandler:

public abstract class soapreceiver : soapport, ihttphandler

{

   。。。

}

<b>由于這一點,任何</b><b> soapreceiver </b><b>或</b><b> sendservice </b><b>類現在都能夠在</b><b> asp.net </b><b>中配置為</b><b> http </b><b>處理程式。</b>通過在 web.config 檔案的 httphandlers 部分添加一個新的映射,使用者能夠配置 http 處理程式。web.config 項将把 verb/path 組合映射到 soapreceiver 類型:

首先,我們通過在web service的配置檔案web.config中,加入如下示範片斷:

&lt;configuration&gt;

  &lt;configsections&gt;

    &lt;section name="microsoft.web.services"

      type="microsoft.web.services.configuration.webservicesconfiguration,

      microsoft.web.services, version=2.0.0.0, culture=neutral,

      publickeytoken=31bf3856ad364e35" /&gt;

  &lt;/configsections&gt;

&lt;system.web&gt;

&lt;httphandlers&gt;

        &lt;!-- 為了讓我們的webservice能夠接收到來自于背景偵聽服務的soap消息

             我們讓webservice繼承自soapreceiver,并實作了void receive(soapenvelope envelope),

             這樣exe通過向

             new uri("http://"+ system.net.dns.gethostname() + "/myservice/getreceiver.ashx")

             發送soap消息,那麼soapreceiver的receive回調函數将被調用

        --&gt;

      &lt;add type="mywebservice.myinterface" path="getreceiver.ashx" verb="*" /&gt;

&lt;/httphandlers&gt;

把這組代碼放到适當的位置,将針對每條輸入此虛拟目錄并指向 getreceiver.ashx 的消息而調用 myservice。現在我們不必擔心通過調用 soapreceiver.add 來配置 soapreceiver/soapservice,因為 asp.net 本質上代替您完成了此任務。

如果windows service通過soapsender,就可以把消息發送到我們定義的 http 終結點(http://localhost/myservice/getreceiver.ashx),它與使用 tcp 信道接收soap消息的工作方式相同,隻是現在它通過 http 進行通訊。

我們在webservice中加上幾個靜态的哈希表,存儲了用戶端的回調函數以及其他資訊,還有對應的查詢請求等,相當于儲存了會話狀态,進而能夠在這些哈希表的幫助下完成與windows服務之間的異步互動,以及與用戶端調用者之間的異步互動。

實作異步 xml web services 方法應遵循 .net framework 異步設計模式。

<b>第一步,将我們的異步</b><b> xml web services </b><b>方法</b><b>getreceive</b><b>拆分成兩個方法。</b><b></b>

每個方法都有相同的基名稱,即一個以 begin 開始,另一個以 end 開始;

<b>第二步,實作異步</b><b>web service</b><b>的</b><b>begingetreceive</b><b>方法:</b><b></b>

begingetreceive 方法的參數清單包含方法功能的所有 in 和 by reference 參數,以及追加到結尾的兩個參數。

by reference 參數作為 in 參數列出。

倒數第二個參數必須為 asynccallback。asynccallback 參數允許用戶端提供委托,在方法完成時将調用該委托。

當一個異步 xml web services 方法調用另一個異步方法時,此參數可被傳遞到該方法的倒數第二個參數。

最後一個參數是 object。object 參數允許調用方為方法提供狀态資訊。當一個異步 xml web services 方法調用另一個異步方法時,此參數将被傳遞到該方法的最後一個參數。

傳回值必須為 iasyncresult 類型。

<b>第三步,實作異步</b><b>web service</b><b>的</b><b>endgetreceive</b><b>方法:</b><b></b>

endgetreceive 方法的參數清單包含 iasyncresult 參數,此參數後面帶有特定于該方法功能的任意 out 和 by reference 參數。

傳回值類型與異步 xml web services 方法的傳回值類型相同。

by reference 參數作為 out 參數列出。

我們與一般的異步web service不同之處在于,begingetreceive 方法中又調用的

iasyncresult arr = prcdelegate.begininvoke(null, callback, asyncstate);

方法是類内部定義的“processreceive”函數,它實際上還是一個異步處理消息過程,它隻是把要處理的查詢請求用soapsender發送給背景服務,之後就傳回,不再等待。

<b>第四步,等到背景服務把結果發送給本</b><b>web service</b><b>的</b><b>http</b><b>終結點,我們再把結果都存儲在哈希表中,然後回調調用者。</b><b></b>

<b>第五步,調用者收到回調後,就調用我們</b><b>web service</b><b>的</b><b>endgetreceive</b><b>方法,進而從哈希表中拿到結果集。</b><b></b>

<b> </b>

上面描述的流程如下一節的圖檔所示。

由于web service運作的身份是asp.net使用者,而soapreceiver.add方法對執行權限要求較高,是以我們采用http終結點的方式,再加上幾個靜态的哈希表,進而完成了與背景偵聽服務之間的異步互動,以及與用戶端調用者之間的異步互動。

[WSE]Web Service與Windows Service通過WSE2.0建立訂閱/釋出關系[更新版]

圖1 互動流程步驟說明

下面我們具體講解一下:

首先,調用者請求web serviced的begingetreceive方法,這個方法再異步調用processreceive方法它負責組裝出一個<b>soapenvelope</b>,并向uri為

soap.tcp://hostname:port/yourreceivername

的目标endpoint,用soapsender.send發送這個<b>soapenvelope</b>。一方面用于通知訂閱關系,另一方面傳遞了各項參數,以及預先生成的guid。之後就将處理權傳回調用者。

這裡包含了圖中的1,2,3三步:

其次,正在監聽的偵聽服務收到了消息,進行處理:

添加這個訂閱者的各種資訊到靜态哈希表;

利用i/o完成端口異步執行各種任務;

把結果集或者錯誤資訊通過web service http終結點通知訂閱者。

這裡包含了圖中的4,5,6三步:

最後,訂閱者web service收到通知後,通知用戶端調用者的回調函數來取回結果集,進而将結果集或者錯誤原因傳回給用戶端。

編寫者:鄭昀@ultrapower