简体   繁体   中英

Can I use WCF duplex binding to relay message?

I have a Client Application, a server and another client, lets call it third party. I have a callback interface as part of my contract that is implemented both by the third party and the client.

The third party will call a server operation(method) then the server will trigger a callback but instead of calling the callback of the third party, it will call the callback implementation of the client.

Yes, you can absolutely do that.

The easiest way is to implement your service as a PerSession service, and capture the callback context on initialization/construction. Typically I will add the service object (which really represents a connection at that point) to an internal core object.

Then, when you get in a message from a client, you can make a call to any of the service objects (not through the contract), and internally forward the data to the associated client.

This is a pretty minimal implementation of the concept, without exception handling, and some pretty bad design (static class BAD!). I haven't tested this, but the principles should hold even if I missed crossing an i or dotting a t. This example also forwards the calls to all clients, but selecting an individual client follows the same basic pattern.

Trying to do this with a singleton service will be more difficult, and a per-call service obviously won't work :)

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IContract
{
    [OperationContract(IsOneWay = true)]
    void SendTheData(string s);
}

public interface ICallback
{
    [OperationContract(IsOneWay = true)]
    void ForwardTheData(string s);
}

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerSession)]
public class ServiceConnection : IContract
{
    private ICallback m_callback;

    public ServiceConnection()
    {
        m_callback = OperationContext.Current.GetCallbackChannel<ICallback>();
        ServiceCore.Add(this);
    }

    public void SendTheData(string s)
    {
        ServiceCore.DataArrived(s);
    }

    public void SendToClient(string s)
    {
        m_callback.ForwardTheData(s);
    }
}

static public class ServiceCore
{
    static private List<ServiceConnection> m_connections = new List<ServiceConnection>();


    public static void DataArrived(string s)
    {
        foreach(ServiceConnection conn in m_connections)
        {
            conn.SendTheData(s);
        }
    }

    public static void Add(ServiceConnection connection)
    {
        m_connections.Add(connection);
    }
}

From a quick read of the Microsoft Duplex service documentation I don't think that will do what you want. There could be some other clever Kung Fu WCF way to do it but in my case I created a "PassThruService" for the server that implemented the same contract as the real service and sent any requests received onto the client.

This is a part of my code that explains the thrust of it.

private const int OPERATION_TIMEOUT = 5000;
private MyServiceClient m_client = new MyServiceClient();

public bool IsAlive() {
    try {
        logger.Debug("PassThruService IsAlive.");

        bool isAlive = false;
        ManualResetEvent isAliveMRE = new ManualResetEvent(false);

        m_client.IsAliveComplete += (s, a) => { isAlive = a.Result; isAliveMRE.Set(); };
        m_client.IsAliveAsync();

        if (isAliveMRE.WaitOne(OPERATION_TIMEOUT)) {
            return isAlive;
        }
        else {
            throw new TimeoutException();
        }
    }
    catch (Exception excp) {
        logger.Error("Exception PassThruService IsAlive. " + excp.Message);
        throw;
    }

I don't fully see what you're really asking here.... but I'll try to give some tips anyway.

Relaying messages or routing is not very well supported in WCF in .NET 3.5 - the infrastructure is there, but it's still a lot of work to set it up manually.

The best intro I know into this topic for WCF in .NET 3.5 is a two-part article by Michele Leroux Bustamante on MSDN magazine:

Part 2 has a section on duplex routers - does that help you in your quest at all??

WCF in .NET 4.0 promises to bring additional support for routing - there will be a RoutingService base class which can be leveraged to write routing services, and it will allow for configurable, content- or metadata-based routing - whatever it is that you need.

.NET 4.0 is scheduled to be released sometime later this year (2009) - hopefully! So while this is still the future, it's looking rosy!

Marc

I think I found the solution..

Here's the link. http://msdn.microsoft.com/en-us/magazine/cc163537.aspx

Try to look at figure 6. That's what I'm trying to achieve.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM