【问题标题】:Wcf Duplex: Retrieve Client Connection?Wcf Duplex:检索客户端连接?
【发布时间】:2010-10-21 10:11:41
【问题描述】:


也许这看起来很荒谬,但至少对我来说这是个问题

我编写了双工 WCF 服务,在我的服务中我需要获取活动客户端服务并保存它们,当发生特殊事件时,我调用特定客户端并为其发送一些值。所以我定义字典并将客户端保存在其中。 (用这个方法客户端调用)

 public static Dictionary<int, IServiceCallbak> ActiveClients;
    public void IConnect(int SenderId)
    {
            if (ActiveClients == null)
                ActiveClients = new Dictionary<int, IServiceCallbak>();
            Client = OperationContext.Current.GetCallbackChannel<IServiceCallbak>();
            if (ActiveClients.Count(ac => ac.Key == SenderId) > 0)
                ActiveClients.Remove(SenderId);
            ActiveClients.Add(SenderId, Client);
    }

那么当我需要从该字典中查找客户端并调用特定方法时:Client.DoSomthing().
此外,当客户端想要退出时,它会调用IDisconnect 方法,该方法将从字典中删除客户端。

所以我在服务中管理 Active-client!!!

But there is problem in client for managing themselvesapp.config 中定义的一段时间后,服务连接将关闭,您应该更新该连接,然后打开服务。

所以在这种情况下:
1)有没有办法在客户端重新创建和打开服务对象automatically
2)或者当服务想要调用客户端时在服务器端,从该字典中检查客户端服务对象的状态,然后从服务器端重新打开连接(Ridiculous-solution

编辑

我认为更好的解决方案是处理Suggestion 1,我不知道该怎么做!!!。
所以现在的问题是:Is way exist to do Suggestion 1 Or not? 之前我在评论中描述了建议 1:
“并自动引用此案例的事件(如关闭或中止),但我在 Service-Client 中找不到任何可以执行此操作的内容”

【问题讨论】:

  • 关于建议1,如果我重新创建服务对象并调用服务,服务会发现具有不同服务回调通道的客户端。所以我的意思是,我使用相同的 Service-Callback-Channel 为服务创建相同的对象。并自动引用此案例的事件(如关闭或中止),但我在 Service-Client 中找不到任何可以执行此操作的内容,但 Service-channel Closing 中有一个事件。那么有什么方法可以使用它吗?

标签: wcf


【解决方案1】:

为了防止服务器端关闭连接,您可以在合约中设置一个 Heartbeat() 方法,客户端可以定期调用该方法。然而,这并不理想,因为底层套接字可能会丢失,而这并不能解决这个问题。

就您的建议而言 1) 如果在客户端您是从 ClientBase 继承的,那么在您调用路由到服务的方法之前可能不会给出任何问题的指示。您必须将调用包装在 try / catch 中,然后使用一些重新连接逻辑:

public class MyClass : ClientBase<IContract>, IContract
{
    public void ServiceMethod(String data) {
        try {
            base.Channel.ServiceMethod(data);
        }
        catch (CommunicationException ce) {
            // Perform some reconnect logic here
            base.Channel.ServiceMethod(data);
        }
    }
}

您对建议 2) 的评论是正确的,如果服务器端和客户端之间有任何防火墙,它们很可能不允许连接

编辑: 要扩展我对 1) 的建议,当调用服务失败并出现 CommunicationException 时,您需要创建一个新连接。最简单的方法是在构造函数中创建服务通道,然后在调用失败时创建另一个:

class ServiceClient {
    Service1Client mService;  // Class generated by VS tool
    public ServiceClient()
        : base() {
            mService = new Service1Client();
    }
    #region IService1 Members
    public string GetData(int value) {
        CommunicationState state = mService.State;
        if (state == CommunicationState.Closed || state == CommunicationState.Faulted) {
            mService = new Service1Client();
        }
        try {
            // Note: The state checked above may not be accurate,
            //  hence the try...catch
            return mService.GetData(value);
        }
        catch (CommunicationException) {
            mService = new Service1Client();  // Reconnect logic
            return mService.GetData(value); // If it fails again we are out of luck...
        }
    }
    #endregion
}

编辑2:

在 WCF 中,会话由客户端处理,如果客户端和服务之间的会话丢失,我知道无法从客户端或服务恢复该会话。不幸的是,你被困在这里了。

如果服务想通过回调发送会话中断,简单地说,它不能。由于网络的工作方式,服务可能不知道实际的客户端地址。这个问题和其他各种问题(如防火墙)意味着尝试从服务重新建立到客户端的连接是不切实际的。服务的唯一方法是存储它想要发送给客户端的数据,并在服务检测到客户端重新连接时发送。

无法保证客户端会知道底层套接字丢失,直到客户端尝试通过套接字发送某些内容,因此 try...catch。一旦发现连接断开,从客户端重新创建通道是我所知道的处理问题的唯一方法;这就是代码示例的作用。

心跳的想法是一种主动处理断开连接的方法。它的效率取决于您对检测断开连接的速度以及存在多少客户端的要求。连接的客户端越多,心跳就必须越长,这样您就不会在服务的网络上增加负载。

编辑3:

经过一些额外的挖掘后,可能会有一种方法可以自动执行您想要的操作。您可以创建所谓的Reliable Session。激活它需要在配置中创建额外的条目:

<netTcpBinding>
    <binding>
        <reliableSession ordered="Boolean"
                    inactivityTimeout="TimeSpan"
                    enabled="Boolean" />
    </binding>
</netTcpBinding>

它也可用于与 Http 相关的绑定,请查看有关该功能的 Microsoft 文档的链接。

【讨论】:

  • @Steve Heartbeat 我喜欢这样,但正如你所说,这不是理想的方式。所以我必须为此制作计时器。(我不喜欢计时器的特别服务)。感谢您的关注!这对我有帮助:)
  • @Steve,再次感谢。我认为您创建了自助服务客户端基类 - 而我使用添加服务引用和 VS 生成该类。所以问题是我可以更改这个生成的类吗?
  • 在这种情况下,您可能不应该更改生成的代码。请参阅我对上面的 ServiceClient 类的编辑,其中它们生成的类由另一个包含自定义代码的类包装。
  • 我在我的回答中加入了 Edit2。
  • 我在我的回答中加入了 Edit3
猜你喜欢
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
相关资源
最近更新 更多