WCF - 回调客户端(双工?)

4
我有一个问题,需要选择什么解决方案。我的服务器运行着一个服务,可以从网站接收订单。与此服务器相连的是几个客户端(远程计算机)。
我很想使用WCF进行所有通信,但不确定是否可能。我不想在客户端路由器中配置所有客户端防火墙设置,因此客户端将必须连接到服务器。但是当服务器接收到订单时,它应该被传输到特定的客户端。一种解决方案可能是让客户端使用双工绑定连接,但必须保持连接处于活动状态,以便能够从服务器接收数据……这是一个好的解决方法吗?
通常,连接会超时,并且很可能有很好的原因……谁能对这个问题有所了解呢?感谢任何建议:-)
最好的问候 Søren Müller

1
谨慎处理在服务器集群中的会话以及重启等事项。 - Pablo Castilla
2个回答

6
这正是双工绑定设计的用途。您有两个最佳选择NetTcpBindingPollingDuplexBinding
前者使用TCP协议,如果您的客户端不在您的网络上,则可能不适合他们。但是,它允许通过客户端发起的套接字进行双向通信。因此,客户端无需能够接受传入连接。我最近在一个项目中使用了它,并且它非常有效。它也非常敏感。当客户端应用程序关闭时,服务器上的会话立即结束。
第二个选项,PollingDuplexBinding,包含在Silverlight SDK中。它使用客户端发起的“长”HTTP请求。该请求等待需要发送到客户端的消息,并在到达时返回客户端请求。然后客户端再次发起新的HTTP请求返回到服务器。换句话说,客户端始终具有挂起的HTTP请求。这在防火墙上运行良好,并且应该在处理互联网客户端时使用。但是,我发现这不如NetTcpBinding响应快。我可能做错了什么,但似乎尝试向已放弃的客户端会话发送回调需要一段时间才能“超时”。
这是我最近项目中使用NetTcpBinding进行双向通信的配置文件示例。请注意,除了对服务限制进行一些微调外,我基本上使用了此绑定的默认设置。但是,你可以调整许多其他内容,例如接收超时、不活动超时等。点击这里了解更多信息。
<configuration>
    <system.serviceModel>

        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceThrottling maxConcurrentCalls="65535" 
                                       maxConcurrentSessions="65535" 
                                       maxConcurrentInstances="65535" />
                </behavior>
            </serviceBehaviors>
        </behaviors>

        <bindings>
            <netTcpBinding>
                <binding maxConnections="65535">
                    <security mode="None" />
                </binding>
            </netTcpBinding>
        </bindings>

        <services>
            <service name="BroadcastService">
                <endpoint address="" binding="netTcpBinding" contract="BroadcastService" />
            </service>
        </services>

    </system.serviceModel>
</configuration>

[ServiceContract( CallbackContract = typeof( IBroadcastCallback ) )]
[ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple )]
public class BroadcastService : IDisposable
{

    [OperationContract(IsInitiating=true)]
    public long Subscribe( Guid clientID )
    {
        // clients call this to initiate the session
    }

    [OperationContract(IsOneWay = true)]
    public void Publish( BroadcastMessage message )
    {
        // client calls this to broadcast a message to
        // all other subscribed clients via callback
    }

}

[ServiceContract( Name = "BroadcastCallback" )]
public interface IBroadcastCallback
{

    [OperationContract( IsOneWay = true, AsyncPattern = true )]
    IAsyncResult BeginBroadcast(BroadcastMessage Message, AsyncCallback callback, object state);

    void EndBroadcast( IAsyncResult asyncResult );

}   // interface

1
啊,听起来不错...由于是通过互联网进行通信,我认为TCPBinding听起来最好。但是为了让服务器异步地向客户端发送数据,客户端需要保持连接活动状态。在绑定上是否有任何设置可以解决这个问题,或者您需要向服务器发送一个心跳“消息”以保持其活动状态?您是否有任何App.config示例,可以用来设置一个良好的TCPBinding?谢谢.. :-) - MüllerDK
1
NetTcpBinding 上有各种超时设置,控制它在没有任何活动时保持打开的时间,但除此之外,您无需进行任何特殊操作即可使其保持活动状态。我主要使用默认设置。我将更新我的答案以包括最近项目中相关的配置信息。 - Josh
我也处于同样的情况,我已经在使用双工通信的nettcp绑定。但是我的问题是当连接数量达到约800个时,客户端变得无响应并抛出“打开操作未在分配的00:01:00超时内完成。此操作分配的时间可能是更长时间的超时的一部分。”即:我正在使用循环来创建与WCF服务器的连接。感谢您对此问题的帮助。 - Mahesh
嗨,谢谢。我成功地通过使用serviceThrottling和maxConnections配置属性来增加最大客户端数量。感谢您的帮助。 <serviceThrottling maxConcurrentCalls="65535" maxConcurrentSessions="65535" maxConcurrentInstances="65535" /> 您有没有想过在给定时间内有多少客户端连接到您的WCF应用程序?以及最大可以连接的客户端数量。非常感谢您的帮助。 - Mahesh

1
我已经进行了一些研究,以选择最佳的双工通信方法。我想到了以下解决方案。 使用wsDualhttpbinding的WCF服务:
如果服务器和客户端都有公共IP,则此方法很好。客户端和服务器使用http进行通信,因此没有防火墙限制。但是,在启动双工通信时,客户端必须与服务器建立单独的连接,因此客户端也需要公共IP。 使用NetTcpbinding的WCF服务:
此方法使用TCP协议进行双工通信,如果您正在使用WCF,则应该采用这种方法。唯一的缺点是某些防火墙会阻止TCP端口。在这种情况下,您需要有防火墙例外。 使用带有Web套接字的WCF NetHttpBinding:
此方法使用http协议,因此没有防火墙限制。在此方法中,客户端发起http连接,然后升级到TCP连接进行双工通信。目前只有win 8或win 2012操作系统支持WCF Web套接字。如果所有服务器和客户端都是wind 8或win 2013,则应采用此方法。

使用第三方框架(SignalR、Xsocket.net)的Web套接字:
这不是WCF,但仍然可以实现REST Web服务或Windows服务应用程序。使用HTTP协议,稍后升级到TCP进行双向通信。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接