C# 使用NetTcpBinding的双工通信-ContractFilter不匹配?
我正在使用NetTcpBinding在客户机和服务器之间打开双工通信通道方面取得缓慢而稳定的进展。(仅供参考,您可以观察我的新手进度和!) 我现在已经成功地通过服务器的防火墙连接到服务器,客户端可以向服务器发出请求 然而,从另一个角度来看,情况并不那么乐观。在我自己的机器上进行测试时,它可以正常工作,但在internet上进行测试时,当我尝试从服务器端发起回调时,会出现错误:C# 使用NetTcpBinding的双工通信-ContractFilter不匹配?,c#,wcf,nettcpbinding,C#,Wcf,Nettcpbinding,我正在使用NetTcpBinding在客户机和服务器之间打开双工通信通道方面取得缓慢而稳定的进展。(仅供参考,您可以观察我的新手进度和!) 我现在已经成功地通过服务器的防火墙连接到服务器,客户端可以向服务器发出请求 然而,从另一个角度来看,情况并不那么乐观。在我自己的机器上进行测试时,它可以正常工作,但在internet上进行测试时,当我尝试从服务器端发起回调时,会出现错误: The message with Action 'http://MyWebService/IWebService/Hel
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).
下面是一些关键的代码位。首先,web界面:
[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);
}
}
那么我做错了什么
编辑:添加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>
您将回调合同列为ISiteServiceExternal
,但您的客户端实现了IWebServiceCallback
。首先解决这个问题,看看你是否成功。感谢@Allon Guralnek,他帮助我注意到了问题所在:
在服务器端,我有:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class WebService : IWebService { ... }
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, Namespace="http://MyWebService")]
class SiteServer : IWebServiceCallback { ... }
在客户方面,我有:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class WebService : IWebService { ... }
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, Namespace="http://MyWebService")]
class SiteServer : IWebServiceCallback { ... }
冲突发生在PerCall
和PerSession
之间。我刚把服务器端改成了PerSession
,然后-休斯顿,我们起飞了
现在,为了让它与安全一起工作。。。请关注我的WCF学习曲线中的下一个激动人心的部分!:) 你的App.config/Web.config看起来怎么样?您是如何实例化自动生成的服务的(您是否传递了
SiteServer
的实例)?简化事情的一些建议:不要在任何地方(在客户端或服务器上)指定名称空间,不要显式实现IWebServiceCallback(通过从string IWebServiceCallback.HelloWorld()中删除IWebServiceCallback.
){
@Allon-为什么不显式地实现IWebServiceCallback?为什么这会产生影响?已经编辑了问题以在其中一个上显示app.configside@Shaul:不,我不认为这不会有什么不同,这是一个清理代码的建议,除非你出于某种原因确实需要明确说明。尽管我认为这是一个原因您的SiteServer类可能用于其他用途(例如业务逻辑),我建议您不要使用它,以允许在不影响类的其他方面的情况下灵活地使用SynchronizationContext
。此外,您应该从客户端删除ServiceBehaviorAttribute
,因为此时不需要它。@Shaul,看起来不错。您没有回答的一个问题是:您正在传递的实例吗将InstanceContext
实例中的SiteServer添加到生成的WebServiceClient
类的构造函数中没有任何区别。IWebServiceCallback接口是由svcutil生成的,它忽略了回调接口的原始名称。无论如何,这都无法解释在我测试时回调工作的原因在我自己的机器上测试,但在互联网上测试时不会。