程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WCF中的Stream操作

WCF中的Stream操作

編輯:關於.NET

WCF Tips之三

WCF支持對Stream對象的操作,尤其對於傳遞size過大 的消息而言,如要考慮傳遞消息的效率,WCF推薦通過Stream進行操作。

然而,WCF對於Stream操作規定了一些限制,在我們編寫相關程序時,需要特別 注意:

1、綁定的限制

如果需要使用Stream操作,可以使用的綁 定只能是BasicHttpBinding,NetTcpBinding以及NetNamedPipeBinding。此外, 在使用Stream操作時,不能使用Reliable Messaging。如果考慮到消息安全,則 此方式是不可取的。

2、對Stream對象的限制

要作為服務操作所 傳遞的消息對象,這樣的對象必須是可序列化的。遺憾的是,FileStream類的定 義卻是不支持序列化的,我們能夠使用的Stream對象,包括Stream, MemoryStream等。使用Stream類對象是大多數Stream操作的首選。

一個 有趣的現象是FileStream與Stream類型的轉換。例如在服務契約的操作中,有如 下的實現:

public Stream TransferDocument(Document document)
{
FileStream stream = new FileStream
(document.LocalPath, FileMode.Open, FileAccess.Read);
return stream;
}

注意,操作TransferDocument()的 返回類型為Stream,而方法的實現中,返回的對象則為FileStream類型。由於 Stream類是FileStream類的父類,這樣的實現沒有問題。

然而,在客戶 端調用該操作時,卻不能將操作的返回值賦給FileStream類型的對象,如下所示 :

FileStream stream=m_service.TransferDocument(doc);

此時 獲得的Stream對象則為null。因而,我們只能這樣調用操作:

Stream stream=m_service.TransferDocument(doc);

但是,還有 一個奇怪的問題是WCF並不支持Stream對象Length屬性的序列化,也就是說,在 客戶端我們不能使用服務操作返回的Stream對象的Length屬性。諸如 stream.Length的調用會拋出NotSupportedException異常。

3、 TransferMode的限制

若要使用Stream操作,必須修改綁定的 TransferMode屬性。該屬性的默認值為Buffered。我們應該根據操作中Stream對 象的參數類型,以決定TransferMode的值分別為Streamed、StreamedRequest或 者StreamedResponse。

4、MaxReceivedMessageSize的限制

MaxReceivedMessageSize屬性的默認值為64kb,如果傳遞的Stream對象 一旦超過了MaxReceivedMessageSize屬性的設置值,則客戶端在操作該對象時, 就會出現CommunicationException異常。因此,我們應根據實際需要設置 MaxReceivedMessageSize的值。MaxReceivedMessageSize屬性的取值范圍為1- 9223372036854775807(Int32.MaxValue)。如果設置值不在該范圍之內,則無 法通過編譯。編程方式設置為:

binding.MaxReceivedMessageSize = 120000;

配置文件的設置方式為:

<binding…… maxReceivedMessageSize="120000"/>

5、操作參數的限制

WCF對包含了Stream對象的操作參數進行嚴格的限制,它只允許這樣的操 作只能包含一個Stream對象,這裡所謂的一個Stream對象,是包含return對象, out和ref對象在內的。也就是說如下的操作定義都是錯誤的:

void Transfer(Stream s1, Stream s2);
void Transfer(Stream s1, out Stream s2);
void Transfer(Stream s1, ref Stream s2);
Stream Transfer(Stream stream);

如果定義了這樣的操作,則 會出現運行時錯誤。

6、實例激活類型的限制

由於Stream操作受 到綁定的限制,只能使用BasicHttpBinding,NetTcpBinding以及 NetNamedPipeBinding綁定,因此必然會影響服務實例的激活類型,最主要的是 對Session模式的影響。首先BasicHttpBinding並不支持Session模式的激活類型 。NetTcpBinding以及NetNamedPipeBinding綁定雖然支持Session模式,但是由 於Stream操作不支持可靠消息傳遞,即不能將ReliableSession設置為true。因 此在定義服務契約的SessionMode時,不能將其值設置為SessionMode.Required ,否則會拋出異常。

實際上,Stream操作(指TransferMode不為 Buffered)本身並不支持Session模式。即使我們在使用NetTcpBinding時,將服 務契約的SessionMode設置為Allowed,並將服務的InstanceContextMode設置為 PerSession,服務的執行方式仍然是PerCall方式。(如果不是Stream操作,這 樣的設置服務應為PerSession模式)

因此,在執行Stream操作時,即使 按照Session模式對服務進行設置,如果我們通過 OperationContext.Current.SessionId去獲得會話ID,其值應該為空。

此外,由於傳輸的Stream對象較大,可能會消耗過長的時間,因而建議增大綁定 的SendTimeout屬性值。例如設置為10分鐘。編程方式設置為:

binding.SendTimeout=TimeSpan.FromMinutes (10);

配置文件的設置方式為:

<binding……sendTimeout="00:10:00&quo t;/>

注意,對綁定的相關設置必須要求服務端與客戶端的配 置一致。最佳實踐是均通過配置文件進行設置。例如在我的應用程序中是這樣設 置的:

<basicHttpBinding>
<binding name="DocumentExplorerServiceBinding"
sendTimeout="00:10:00"
transferMode="Streamed"
messageEncoding="Text"
textEncoding="utf-8"
maxReceivedMessageSize="9223372036854775807">
</binding>
</basicHttpBinding>
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved