【问题标题】:WCF client connection issueWCF 客户端连接问题
【发布时间】:2010-11-19 22:13:46
【问题描述】:

我正在使用 VSTS2008 + C# + .Net 3.5 开发托管在 IIS 中的 WCF 服务。然后我使用 VSTS 2008 中的 Add Service Reference 功能自动生成客户端代理代码。

我的问题是,假设我创建了一个客户端代理实例,然后使用这个特定的实例来调用 WCF 服务在服务器端公开的各种方法。那么,每次我进行方法调用时,它会建立一个新的连接吗?或者客户端和服务器之间会有一个恒定的连接(即连接的生命周期是从客户端代理实例的创建到客户端代理实例的处置)?

我正在使用 basicHttpBinding。

【问题讨论】:

    标签: c# .net wcf wcf-client


    【解决方案1】:

    连接一直保持到代理被释放。

    编辑

    至少如果您使用可靠的消息传递,它将保持 TCP 连接打开。我基于此,如果 TCP 连接丢失,可靠的消息传递会失败。见:

    http://codeidol.com/csharp/wcf/WCF-Essentials/Reliability/

    编辑 2

    我收回关于 using 语句的评论。见:

    http://msdn.microsoft.com/en-us/library/aa355056.aspx

    有点离题,但我们已经停止使用添加服务引用,而是使用此处描述的方法:

    http://www.dnrtv.com/default.aspx?showNum=103

    注意:这仅在您同时控制客户端和服务器时才有效。

    【讨论】:

    • 谢谢,这是否意味着底层 TCP 连接在代理处理之前保持打开(活动)?
    • 不,你不应该。将代理包装在 using 中是一个坏主意,就好像在处于故障状态的代理上调用 Dispose 然后它会引发异常,从而首先隐藏导致故障的异常。
    • 谢谢 Shiraz,如果我没有使用可靠的消息传递并且只使用 basicHttpBinding 的默认设置,那么底层连接是否会一直存在?还是每次我们调用一个方法都会有一个新的连接?
    • 嗨吹镖,你对我原来的问题的回答怎么样? :-)
    • 嗨 Shiraz,我看了你推荐的视频 10 分钟,它真的很酷也很有用,但它是否包含有关使用添加服务参考的替代方法的信息?请帮忙澄清一下,谢谢。
    【解决方案2】:

    连接将在底层通道关闭时关闭 - 默认情况下,BasicHttpBinding 在消息中发送一个带有 Keep-Alive 值的连接 HTTP 标头,这使客户端能够与支持它们的服务建立持久连接 /em>。

    这并不意味着服务的实例保持活动状态,只是与网络服务器的连接,如果网络服务器支持的话。

    如果您希望在每次调用后关闭连接,那么您可以通过定义自定义绑定在服务器端将其关闭

    <services> 
     <service>
      <endpoint address=""
            binding="customBinding"
            bindingConfiguration="HttpBinding" 
            contract="IContract" />
     </service>
    </services>
    
    <bindings>
     <customBinding>
       <binding name="HttpBinding" keepAliveEnabled="False"/>
     </customBinding>
    </bindings>
    

    连接将根据您的代理挂起的时间关闭,如果需要,生成的代理将再次重新打开它。

    【讨论】:

    • 谢谢!两个混淆,1.“这并不意味着服务的实例保持活动状态” - 你的意思是“服务的实例保持活动状态”? 2.“如果网络服务器支持的话。” -- 对于IIS,如何判断是否支持?
    • 对不起,还有两个混淆,3.“如果需要,生成的代理将再次重新打开它。” -- 底层 WCF 会自动处理它,如果连接关闭并重新打开不会抛出异常?不需要开发人员处理这种情况? 4.“连接将根据您的代理挂起的时间关闭”——它是否可配置?
    • “服务实例”是指 Web 服务器计算机上实现服务契约的类的实例。有些人假设当您创建代理实例时,它会创建服务实例。这不是真的。
    • 感谢 John, 1. 我认为何时创建或重用实例取决于实例化行为,对吗? 2. 对我的问题 2、3 和 4,你们的 cmets 怎么样? :-)
    • 2.默认情况下,IIS 支持保持活动状态。 3. 是的。 4. 您可以配置超时,但要发现关闭底层连接的确切标准将意味着检查 .NET 源。最后,这真的不应该是你关心的事情。
    【解决方案3】:

    George,要考虑的一件事是,您的代码应尽量不关心连接如何、是否或何时打开或关闭。这主要是频道关心的问题,频道应该能够按照它认为合适的方式管理连接,而不必担心您编写的代码取决于频道“管理自己的业务”的方式。

    只有当您发现或怀疑存在性能问题时,您才应该担心这样的实现细节。如果您担心可能存在这样的问题,请创建一个快速的概念验证应用程序,并使用 Fiddler 或其他工具观察网络流量。在大多数情况下,这将是浪费时间。

    【讨论】:

    • 谢谢约翰,我完全同意你的看法。目前我在将大数据从服务器传输到客户端时遇到了一个问题。这是我的问题stackoverflow.com/questions/1281269/…我怀疑openTimeout参数是否会导致这个问题,我想我需要知道每次我进行方法调用时需要建立连接还是只打开一次。如果只打开一次,这个参数应该不会导致这个问题,因为我在这个错误方法调用之前做了一些成功的方法调用,但是如果需要建立连接
    • (续)每次,我认为这个参数可能会影响结果。此参数的任何 cmets 或是否需要在每次发生方法调用时或仅一次时建立连接?
    • 即使需要多次建立自己,每次都会使用配置的参数。
    【解决方案4】:

    那么,每次我调用一个方法,它会建立一个新的连接吗?

    是的,这是默认行为和首选行为 - 它可以为您节省很多痛苦!

    “这并不意味着服务的实例保持活动状态” - 你的意思是“服务的实例保持活动状态”?

    在“每次调用”服务的默认和首选情况下,会发生以下情况:

    • 客户端代理向服务发出调用
    • 消息在客户端序列化并通过网络发送
    • 服务器端有一个“通道侦听器”,它将接收该消息并查看哪个服务类将处理调用
    • 服务器端的消息调度程序将实例化“YourServiceClass”的一个实例
    • 服务器端的消息调度程序现在将在新创建的服务类实例上调用该方法,并获取结果并将它们打包以供响应
    • 服务器端的服务类对象被释放
    • 响应将发送回您的客户

    这就是您的服务类应该尽可能精简、尽可能独立于其他任何东西的原因之一 - 它们通常会在每个请求进入时被实例化,然后被释放。

    这似乎是一个非常糟糕的主意 - 但如果您的服务对象实例徘徊较长时间,您将不得不做大量的簿记以跟踪它们的状态等等,所以最后,实际上更容易(通常更安全、更简单)创建一个服务类,让它处理请求,然后再次释放它。

    马克

    【讨论】:

    • 嗨,马克,我很困惑。从与吹镖的讨论来看,似乎保持活动是默认行为,如果保持活动,连接应该只在我们进行第一次方法调用时建立一次,而不是在每次进行方法调用时打开/关闭。有cmets吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    相关资源
    最近更新 更多