[英]Detecting Client Death in WCF Duplex Contracts
我正在嘗試構建一個SOA,客戶端可以在服務器上執行長時間運行的查詢,服務器使用回調進行響應。
我希望能夠檢測客戶端是否斷開連接(通過用戶啟動的關閉,未處理的異常或丟失網絡連接),以便服務器可以選擇取消昂貴的請求。
我正在測試各種故障情況,但我似乎無法啟動某些事件處理程序。
經過測試的失敗案例:在請求后殺死客戶端進程。 使用像CurrPorts這樣的程序來關閉TCP連接。
測試代碼:
using System;
using System.ServiceModel;
using System.Threading;
namespace WCFICommunicationObjectExperiments
{
class Program
{
static void Main(string[] args)
{
var binding = new NetTcpBinding(SecurityMode.None);
var serviceHost = new ServiceHost(typeof (Server));
serviceHost.AddServiceEndpoint(typeof (IServer), binding, "net.tcp://localhost:5000/Server");
serviceHost.Open();
Console.WriteLine("Host is running, press <ENTER> to exit.");
Console.ReadLine();
}
}
[ServiceContract(CallbackContract = typeof(IClient))]
public interface IServer
{
[OperationContract]
void StartProcessing(string Query);
}
public interface IClient
{
[OperationContract]
void RecieveResults(string Results);
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Server : IServer
{
public void StartProcessing(string Query)
{
Thread.Sleep(5000);
//Callback Channel
var clientCallback = OperationContext.Current.GetCallbackChannel<IClient>();
var clientCallbackCommunicationObject = ((ICommunicationObject) clientCallback);
EventHandler faultedHandlerCallback = (o, s) => Console.WriteLine("Client Channel Faulted.");
EventHandler closedHandlerCallback = (o, s) => Console.WriteLine("Client Channel Closed.");
clientCallbackCommunicationObject.Faulted += faultedHandlerCallback;
clientCallbackCommunicationObject.Closed += closedHandlerCallback;
//Request Channel
var requestChannel = OperationContext.Current.Channel;
EventHandler faultedHandlerRequest = (o, s) => Console.WriteLine("Request Channel Faulted.");
EventHandler closedHandlerRequest = (o, s) => Console.WriteLine("Request Channel Closed.");
requestChannel.Faulted += faultedHandlerRequest;
requestChannel.Closed += closedHandlerRequest;
try
{
clientCallback.RecieveResults("42.");
}
catch (CommunicationObjectAbortedException ex)
{
Console.WriteLine("Client Aborted the connection");
}
catch (CommunicationObjectFaultedException ex)
{
Console.WriteLine("Client Died.");
}
clientCallbackCommunicationObject.Faulted -= faultedHandlerCallback;
clientCallbackCommunicationObject.Faulted -= closedHandlerCallback;
requestChannel.Faulted -= faultedHandlerRequest;
requestChannel.Closed -= closedHandlerRequest;
}
}
public class ClientToTestStates : IClient
{
private IServer m_Server;
private readonly ManualResetEvent m_ReceivedEvent = new ManualResetEvent(false);
private readonly ManualResetEvent m_ChannelFaulted = new ManualResetEvent(false);
private readonly ManualResetEvent m_ChannelClosed = new ManualResetEvent(false);
public ClientToTestStates()
{
var binding = new NetTcpBinding(SecurityMode.None);
var channelFactory = new DuplexChannelFactory<IServer>(this, binding, new EndpointAddress("net.tcp://localhost:5000/Server"));
m_Server = channelFactory.CreateChannel();
((ICommunicationObject)m_Server).Open();
((ICommunicationObject)m_Server).Faulted += ChannelFaulted;
((ICommunicationObject)m_Server).Closed += ChannelClosed;
m_Server.StartProcessing("What is the answer?");
WaitHandle.WaitAny(new WaitHandle[] {m_ReceivedEvent, m_ChannelFaulted, m_ChannelClosed});
}
void ChannelFaulted(object sender, EventArgs e)
{
m_ChannelFaulted.Set();
Console.WriteLine("Channel Faulted.");
}
void ChannelClosed(object sender, EventArgs e)
{
m_ChannelClosed.Set();
Console.WriteLine("Channel Closed.");
}
public void RecieveResults(string results)
{
m_ReceivedEvent.Set();
Console.WriteLine("Recieved Results {0}", results);
}
}
}
處理這類失敗案例的最佳做法是什么? 我希望能夠使用底層的tcp連接來檢測其中的一些內容。
在他的“編程WCF服務”一書中,Juval Lowy解釋說WCF沒有提供管理服務回調的機制,這必須由服務和客戶端明確管理。 如果服務嘗試調用已在客戶端上關閉的回調,則將在服務通道上拋出ObjectDisposedException。
他建議在服務合同中添加Connect和Disconnect方法 - 因為在調用這些服務時必須向服務提供回調,該服務可以管理客戶端回調。 然后由客戶端確保在不再希望從服務接收回調時調用Disconnect,並且服務必須在調用客戶端的回調時處理任何異常。
嘗試這個來檢查回調對象是否仍然有效:
(((ICommunicationObject)myCallbackObject).State == CommunicationState.Opened)
在這種情況下,myCallbackObject是您可以通過其執行回調的對象,即實現回調協定的對象
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.