【问题标题】:Duplex communication using NetTcpBinding - ContractFilter mismatch?使用 NetTcpBinding 进行双工通信 - ContractFilter 不匹配?
【发布时间】:2010-12-26 18:21:44
【问题描述】:

我在使用 NetTcpBinding 在客户端和服务器之间打开双工通信通道方面取得了缓慢而稳定的进展。 (仅供参考,你可以观察我的新手进度herehere!)

我现在已经成功连接到我的服务器,通过服务器的防火墙,客户端可以向服务器发出请求。

然而,在另一个方向上,事情并不那么令人愉快。在我自己的机器上测试时它工作正常,但是在通过互联网测试时,当我尝试从服务器端发起回调时,我收到一个错误:

The message with Action 'http://MyWebService/IWebService/HelloWorld' cannot be
processed at the receiver, 
due to a ContractFilter mismatch at the EndpointDispatcher. 
This may be because of either a contract mismatch (mismatched Actions between 
sender and receiver) 
or a binding/security mismatch between the sender and the receiver.  
Check that sender and receiver have the same contract and the same binding 
(including security requirements, e.g. Message, Transport, None).

这里是一些关键的代码。一、网页界面:

[ServiceContract(Namespace = "http://MyWebService", SessionMode = SessionMode.Required, CallbackContract = typeof(ISiteServiceExternal))]
public interface IWebService {
  [OperationContract]
  void Register(long customerID);
}

public interface ISiteServiceExternal {
  [OperationContract]
  string HelloWorld();
}

IWebService 的实现如下:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class WebService : IWebService {
  void IWebService.Register(long customerID) {
    Console.WriteLine("customer {0} registering", customerID);
    var callbackService = OperationContext.Current.GetCallbackChannel<ISiteServiceExternal>();
    RegisterClient(customerID, callbackService);
    Console.WriteLine("customer {0} registered", customerID);
  }
}

然后,在客户端(我在不知道自己在做什么的情况下摆弄这些属性):

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, Namespace="http://MyWebService")]
class SiteServer : IWebServiceCallback {
  string IWebServiceCallback.HelloWorld() {
return "Hello World!";
  }
  ...
}

那么我在这里做错了什么?

编辑: 添加 app.config 代码。从服务器:

<system.serviceModel>
  <diagnostics>
    <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
        logMessagesAtTransportLevel="true" logEntireMessage="true" maxMessagesToLog="1000" maxSizeOfMessageToLog="524288" />
  </diagnostics>
  <behaviors>
    <serviceBehaviors>
      <behavior name="mex">
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <serviceMetadata/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service name ="MyWebService.WebService" behaviorConfiguration="mex">
      <endpoint address="net.tcp://localhost:8000" binding="netTcpBinding" contract="MyWebService.IWebService"
                bindingConfiguration="TestBinding" name="MyEndPoint"></endpoint>
      <endpoint address ="mex"
                binding="mexTcpBinding"
                name="MEX"
                contract="IMetadataExchange"/>
      <host>
        <baseAddresses>
          <add baseAddress="net.tcp://localhost:8000"/>
        </baseAddresses>
      </host>
    </service>
  </services>
  <bindings>
    <netTcpBinding>
      <binding name="TestBinding" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" portSharingEnabled="false">
        <readerQuotas maxDepth="32" maxStringContentLength ="8192" maxArrayLength ="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
        <security mode="None"/>
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>

在客户端:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="MyEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00"
          receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
          transferMode="Buffered" transactionProtocol="OleTransactions"
          hostNameComparisonMode="StrongWildcard" listenBacklog="10"
          maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
          maxReceivedMessageSize="65536">
        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
        <reliableSession ordered="true" inactivityTimeout="00:10:00"
            enabled="false" />
        <security mode="None">
          <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign">
            <extendedProtectionPolicy policyEnforcement="Never" />
          </transport>
          <message clientCredentialType="Windows" />
        </security>
      </binding>
    </netTcpBinding>
  </bindings>
  <client>
    <endpoint address="net.tcp://mydomain.gotdns.com:8000/" binding="netTcpBinding"
        bindingConfiguration="MyEndPoint" contract="IWebService" name="MyEndPoint" />
  </client>
</system.serviceModel>

【问题讨论】:

  • 您的 App.config/Web.config 看起来如何?你如何实例化你的自动生成的服务(你是否传入了SiteServer 的实例)?一些简化事情的建议:不要在任何地方(在客户端或服务器上)指定命名空间,不要显式实现 IWebServiceCallback(通过从 string IWebServiceCallback.HelloWorld() { 中删除 IWebServiceCallback.
  • @Allon - 为什么不显式实现 IWebServiceCallback?为什么会有所作为?
  • 已编辑问题以在任一侧显示 app.config
  • @Shaul:不,我认为这不会有什么不同,这是清理代码的建议,除非您出于某种原因确实需要明确说明。尽管我认为这样的原因是您的 SiteServer 类可能用于其他事情(例如业务逻辑),但我不建议这样做,以允许UseSynchronizationContext 的灵活性而不影响该类的其他方面。此外,您应该从客户端删除ServiceBehaviorAttribute,因为此时不需要它。
  • @Shaul,看起来不错。您没有回答的一个问题:您是否将 InstanceContext 实例中的 SiteServer 实例传递给生成的 WebServiceClient 类的构造函数?

标签: c# wcf nettcpbinding


【解决方案1】:

感谢@Allon Guralnek,他帮助我发现了问题所在:

在服务器端我有:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class WebService : IWebService { ... }

在客户端我有:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, Namespace="http://MyWebService")]
class SiteServer : IWebServiceCallback { ... }

冲突发生在PerCallPerSession 之间。我刚刚将服务器端更改为PerSession,并且 - 休斯顿,我们起飞了!

现在,为了让这个与安全性一起工作...观看我的 WCF 学习曲线中的下一个激动人心的部分! :)

【讨论】:

    【解决方案2】:

    您将回调合约列为ISiteServiceExternal,但您的客户端实现了IWebServiceCallback。先解决这个问题,看看是否成功。

    【讨论】:

    • 没有区别。 IWebServiceCallback 接口由 svcutil 生成,它忽略了回调接口的原始名称。无论如何,这无法解释为什么回调在我自己的机器上测试时有效,但在互联网上测试时无效。
    猜你喜欢
    • 2014-08-22
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 2018-07-05
    相关资源
    最近更新 更多