WCF中的Stream操作

2022-02-21 13:34:17 字數 3381 閱讀 8231

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)

注意,操作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, 

outstream s2);

void

transfer(stream s1, 

refstream 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

"/>

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

WCF中的Stream操作

wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意 1 繫結的限制 如果需要使用stream操作,可以使用的繫結只能是basichttp...

WCF中的Stream操作

wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意 1 繫結的限制 如 果需要使用stream操作,可以使用的繫結只能是basichtt...

WCF中的Stream操作

wcf支援對stream物件的操作,尤其對於傳遞size過大的訊息而言,如要考慮傳遞訊息的效率,wcf推薦通過stream進行操作。然而,wcf對於stream操作規定了一些限制,在我們編寫相關程式時,需要特別注意 1 繫結的限制 如 果需要使用stream操作,可以使用的繫結只能是basichtt...