2010-10-27 84 views
9

嗯,我完全失去了任何幫助,將不勝感激雙工系統WCF如何區分不同的通道實例?

的 OperationContext.Current.InstanceContext 是當前服務 實例的背景下,輸入通道是 使用。

在雙工系統中,該服務可以通過 CallbackContract向客戶端回撥 。此 CallbackContract非常類似於客戶端上的 服務,即 正在偵聽客戶端打開的客戶端的服務 上的呼叫 。這種「客戶端回調 服務」只能通過它的服務 使用的 相同的信道進行訪問,因此僅該服務具有 訪問它。

a)因此,在雙工系統中,客戶端向服務發送消息的同一個通道實例也被客戶端用於接收來自服務的消息? b)如果在請求 - 回覆系統中客戶端使用特定的信道實例clientChannel向服務發送消息,那麼我假設這個相同的實例(因此clientChannel)需要保持打開狀態,直到服務發送迴應給這個實例,而雙工系統clientChannel需要保持打開狀態直到會話關閉?

三)我假設這樣的行爲,因爲據我可以告訴每個通道實例都有一個唯一的地址(或ID),這有助於從其他渠道情況區別開來)在同一客戶端上運行?當服務發回消息時,它還指定了此頻道的ID?

因此,當在雙面打印系統客戶端調用服務,WCF創建(在客戶側)的信道實例clientChannel,其通過線路發送消息。在服務器端,WCF創建通道實例serverChannel,它將消息傳遞到請求的操作(方法)。當這種方法想要經由CallbackContract回調到客戶端,它使用InstanceContext.GetCallBackChannel<>創建一個信道,這除其它外包含稱爲服務信道的ID(因此它包含的clientChannel一個確切的地址或ID)?

d)在雙工系統客戶端是否使用同一個通道實例調用任何端點的操作?

謝謝

+0

我讀過一些可以澄清一點的東西,但仍然給出了關於雙綁定伏都教的一些答案:TCP和命名管道傳輸協議隱含地支持回調。他們總是可以回到客戶端。對於HTTP,DuplexClientBase 通過在客戶端上託管服務並在端口80上偵聽來自服務的消息的臨時http地址來處理客戶端端點的創建。 – Trevor 2013-02-07 10:18:57

回答

6

我不知道,但這裏是我的理解這一個雙工模式通信。

我看了一下使用反編譯dotPeek的System.ServiceModel集中定義的類的InstanceContext。

在內部有一個呼叫

this.channels = new ServiceChannelManager(this); 

這意味着,它使用的是ServiceChannelManager通過在相同的InstanceContext的實例創建信道。 這樣,它通過InstanceContext的實例來跟蹤Channel。

則結合輸入通道(服務於客戶端),它爲實現在方法請求:

internal void BindIncomingChannel(ServiceChannel channel) 
    { 
     this.ThrowIfDisposed(); 
     channel.InstanceContext = this; 
     IChannel channel1 = (IChannel) channel.Proxy; 
     this.channels.AddIncomingChannel(channel1); 
     if (channel1 == null) 
     return; 
     switch (channel.State) 
     { 
     case CommunicationState.Closing: 
     case CommunicationState.Closed: 
     case CommunicationState.Faulted: 
      this.channels.RemoveChannel(channel1); 
      break; 
     } 
    } 

因此,要回答您的疑問:

一個。是的,它在內部維護Client和Service之間的 調用的Service和InstanceContext(它創建一個通道)關係。

b。是的,頻道需要保持打開狀態,直到服務回覆到上下文,其中InstanceContext 將負責關閉頻道。

c。每個客戶端都有一個唯一的會話ID,但服務上的InstanceContext類型取決於服務在實施合同時使用的InstanceContextMode 。 d)。它使用相同的頻道。 InstanceContext維護IncomingChannel和Outgoing頻道的計數。 傳入通道是指向服務的客戶端和傳出的客戶端到服務的對象。 您可以在VS中使用調試器來查看此計數。

爲了進一步澄清起見,儘可能爲雙工服務的其他行爲來看,這裏是我們如何看待的InstanceContext的行爲,以及如何通道實例被創建:

我創建了一個雙工服務演示:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceDuplexCallback))] 
public interface IServiceClass 
{ 
    [OperationContract(IsOneWay = true)] 
    void Add(int num1); 
} 

本合同爲執行:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
public class ServiceClass : IServiceClass 
{ 
    int result = 0; 

    public void Add(int num1) 
    { 
     result += num1; 
     callBack.Calculate(result); 
    } 

    IServiceDuplexCallback callBack 
    { 
     get 
     { 
      return OperationContext.Current.GetCallbackChannel<IServiceDuplexCallback>(); 
     } 
    } 
} 

在此實現注意到的第一行,其中InstanceConte xtMode被設置爲PerCall。 默認是PerSession。

此枚舉有三個選項:

  1. PerCall - 的InstanceContext的新實例用於每個呼叫無關的會議

  2. PerSession - 新的實例用於每個會話

  3. 單 - 用於所有客戶端的InstanceContext的單個實例。

我創建了使用NetTcpBinding的與服務連接的客戶端:

InstanceContext ic = new InstanceContext(new TCPCallbackHandler(ref textBox1)); 
TCP.ServiceClassClient client = new TCP.ServiceClassClient(ic); 

// First call to Add method of the Contract 
client.Add(val1); 
// Second call to Add method of the Contract 
client.Add(val2); 

TCPCallbackHandler是實現回調合同的客戶端類:

public class TCPCallbackHandler : TCP.IServiceClassCallback 
{ 
    TextBox t; 

    public TCPCallbackHandler(ref TextBox t1) 
    { 
     t = t1; 
    } 

    public void Calculate(int result) 
    { 
     t.Text += OperationContext.Current.SessionId + " " + result.ToString(); 
    } 
} 

要查看InstanceContext的行爲,我開始了服務,然後啓動了兩個客戶端,每個枚舉操作都使用 ,如上所述。下面是結果:

1 - PerCall

客戶1:金塔:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 甕:UUID:4c5f3d8b-9203-4f25-b09a- 839089ecbe54

客戶端2:甕:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01 - 甕:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01

這裏 - 甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54是SessionID的

由於每個客戶端添加在客戶端調用兩次,並在PerCall - >的InstanceContext的新實例創建的每個呼叫,我們爲每個客戶端的調用創建一個新的ServiceClass實例。這裏要注意的是,新的實例,即使是同一個會話

//第一次調用添加合同

client.Add(VAL1)的方法創建的; - >服務類的新實例創建和值將被遞增到5

//第二呼叫添加合同的方法

client.Add(val2次); - >服務類的新實例創建和值將被遞增到5

2 - PerSession

客戶端1:甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54

客戶端2:甕:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01 - 甕:UUID:e101d2a7-ae41-4929-9789 -6d43abf97f01

這裏,ServiceClass的實例對客戶端來說是分開的,因爲它們有不同的會話在運行。因此,在呼叫的增量是0 - > 5 - > 10(爲客戶端分開)

3 - 單

客戶端1:甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54

客戶端2:甕:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01 - 甕:UUID:e101d2a7- ae41-4929-9789-6d43abf97f01

這裏所有的客戶端共享同一個ServiceClass實例,所以我們在第一個客戶端有0 - > 5 - > 10。第二個客戶端將在同一個實例中增加,所以我們得到10 - > 15 - > 20。

這將有不同的行爲,根據調用,可能會給出像從客戶端同時調用的結果。

客戶端1:甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 甕:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54

客戶端2:甕:UUID :e101d2a7-ae41-4929-9789-6d43abf97f01 - 甕:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01

希望這有助於!