Дуплексная связь с использованием NetTcpBinding - несоответствие ContractFilter? - PullRequest
2 голосов
/ 26 декабря 2010

Я медленно и уверенно продвигаюсь к открытию дуплексного канала связи между клиентом и сервером, используя NetTcpBinding.(К вашему сведению, вы можете наблюдать за моим прогрессом новичка здесь и здесь !)

Я сейчас на этапе, когда я успешно подключился к своему серверу черезбрандмауэр сервера, и клиент может делать запросы к серверу.

В другом направлении, однако, все не так радует.Он отлично работает при тестировании на моей собственной машине, но при тестировании через Интернет, когда я пытаюсь инициировать обратный вызов со стороны сервера, я получаю сообщение об ошибке:

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>

Ответы [ 2 ]

3 голосов
/ 27 декабря 2010

Благодарность @Allon Guralnek, который помог мне заметить, что случилось:

На стороне сервера у меня было:

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

А на стороне клиента у меня было:

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

Конфликт был между PerCall и PerSession. Я просто изменил серверную сторону на PerSession, и - Хьюстон, у нас взлет!

Теперь, чтобы это работало с безопасностью ... смотрите ТАК для следующей захватывающей статьи в моей кривой обучения WCF! :)

0 голосов
/ 26 декабря 2010

Вы указали свой контракт обратного вызова как ISiteServiceExternal, но ваш клиент реализует IWebServiceCallback. Сначала исправьте это и посмотрите, есть ли у вас успех.

...