本文介绍了检测客户端在死亡WCF双工协定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想建立一个SOA,在这里客户可以在服务器上执行长时间运行的查询和使用回调的服务器响应。

I'm trying to build a SOA where clients can perform long running queries on the server and the server responds using a callback.

我希望能够检测如果客户端断开连接(通过用户启动的关机,未处理的异常或丢失网络连接),使服务器可以选择取消昂贵的请求。

I'd like to be able to detect if the client disconnects (through user initiated shutdown, unhandled exception or loss of network connectivity) so that the server can choose to cancel the expensive request.

我测试了各种失败的案例,但我似乎无法得到某些事件处理火灾。

I'm testing a variety of failure cases but I can't seem to get certain event handlers to fire.

测试失败的案例:
查杀客户端进程请求后。
使用程序一样CurrPorts关闭TCP连接。

Tested Failure Cases:Killing the Client Process After the request.Using a program like CurrPorts to close the TCP Connection.

测试code:

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连接,以检测其中的一些东西。

What's the best practice to handle these sorts of failure cases? I'd like to be able to use the underlying tcp connection to detect some of these things.

推荐答案

在他的编程WCF服务的书,Juval洛伊解释说,WCF不用于管理服务的回调提供了一个mechansim,而这必须由服务和管理客户明确。如果该服务试图调用已关闭了客户端上的回调,一个的ObjectDisposedException将在服务通道被抛出。

In his 'Programming WCF Services' book, Juval Lowy explains that WCF does not provide a mechansim for managing service callbacks, and this must be managed by the service and client explicitly. If the service attempts to invoke a callback which has been closed on the client, an ObjectDisposedException will be thrown on the service channel.

他建议增加一个连接和断开的方法来服务合同 - 因为回调必须提供给当这些被称为,该服务可以管理客户端回调的服务。它是那么到客户端,以保证它调用断开连接时,它不再希望从服务收到回调,并调用回调到客户端服务必须处理任何异常。

He recommends adding a Connect and Disconnect method to the service contract - since the callback must be provided to the service when these are called, the service can manage client callbacks. It is then up to the client to ensure that it calls Disconnect when it no longer wishes to recieve callbacks from the service, and the service must handle any exceptions when invoking callbacks to the client.

这篇关于检测客户端在死亡WCF双工协定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 06:53
查看更多