我不知道,但這裏是我的理解這一個雙工模式通信。
我看了一下使用反編譯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。
此枚舉有三個選項:
PerCall - 的InstanceContext的新實例用於每個呼叫無關的會議
PerSession - 新的實例用於每個會話
單 - 用於所有客戶端的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
希望這有助於!
我讀過一些可以澄清一點的東西,但仍然給出了關於雙綁定伏都教的一些答案:TCP和命名管道傳輸協議隱含地支持回調。他們總是可以回到客戶端。對於HTTP,DuplexClientBase通過在客戶端上託管服務並在端口80上偵聽來自服務的消息的臨時http地址來處理客戶端端點的創建。 –
Trevor
2013-02-07 10:18:57