我在过去的两天里一直在和WCF合作,而且我的开发机器上的服务器和客户端都很顺利.既然我正试图在网络上的另一台机器上与客户端进行一些分布式测试,我就开始遇到问题了.现在我得到的错误是:
由于EndpointDispatcher上的ContractFilter不匹配,因此无法在接收方处理带有Action'http://tempuri.org/IWindowUpdateContract/UpdateWindowFrames ' 的消息.这可能是由于合同不匹配(发送方与接收方之间的操作不匹配)或发送方与接收方之间的绑定/安全性不匹配.检查发送方和接收方是否具有相同的合同和相同的绑定(包括安全要求,例如消息,传输,无).
因为这已经是一个巨大的学习经验(我之前没有做任何远程处理,RPC等)我想继续开发学习工具并在我完成时重新访问安全性(我无意构建任何实际的东西)在没有适当的安全最佳实践的情况下使用).
笔记:
我没有为WCF配置文件 - 我正在以编程方式执行所有操作.
我的网络不是域的一部分,因此默认的安全设置对我不起作用(使用net.tcp).
我正在使用'.Net 3.5'.
我的服务器是这样创建的:
var svh = new ServiceHost(_serviceImplementation); var binding = new NetTcpBinding(); binding.ReaderQuotas.MaxArrayLength = 2000000; binding.Security.Mode = SecurityMode.None; binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; binding.Security.Transport.ProtectionLevel = ProtectionLevel.None; binding.Security.Message.ClientCredentialType = MessageCredentialType.None; svh.AddServiceEndpoint(_serviceInterface, binding, string.Format("net.tcp://{0}:{1}", _endPoint.Address, _endPoint.Port)); _stopFlag = new AutoResetEvent(false); svh.Open(); _stopFlag.WaitOne();
我的客户端是这样创建的:
var binding = new NetTcpBinding(); binding.ReaderQuotas.MaxArrayLength = 2000000; binding.Security.Mode = SecurityMode.None; binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; binding.Security.Transport.ProtectionLevel = ProtectionLevel.None; binding.Security.Message.ClientCredentialType = MessageCredentialType.None; var scf = new ChannelFactory(binding, "net.tcp://192.168.0.42:8001"); _uiUpdateServer = scf.CreateChannel();
我的合同(它只是在作为客户端和服务器的引用添加的类库中)是:
[ServiceContract(ProtectionLevel = ProtectionLevel.None)] public interface IWindowUpdateContract { [OperationContract] void UpdateWindowFrames(WindowFrame frame); [OperationContract] void WindowHasClosed(IntPtr hwnd); }
我觉得我所做的绑定和合同设置应该使它们相同,我不应该有这个问题(应该关闭安全性).我只是不知道现在去哪里.
我同意你的意见 - 看起来服务器和客户端的安全设置是相同的.
旁边的注释:一旦你这样做:
binding.Security.Mode = SecurityMode.None;
我认为你不需要在"binding.Security"对象或下面指定任何更多设置 - 之后不需要那些额外的行.
引起我注意的是你的服务合同:
[ServiceContract(ProtectionLevel = ProtectionLevel.None)] public interface IWindowUpdateContract { [OperationContract] void UpdateWindowFrames(WindowFrame frame); [OperationContract] void WindowHasClosed(IntPtr hwnd); }
那些操作不返回任何东西 - 这是不寻常的.WCF服务的默认行为是请求/响应 - 您发送请求并返回响应.
要么让它们返回一些东西(一个状态等等;像一个字符串,一个int),或者你需要将它们标记为"单向"调用,以便WCF知道不会期待任何回复:
[ServiceContract(ProtectionLevel = ProtectionLevel.None)] public interface IWindowUpdateContract { [OperationContract(IsOneWay=true)] void UpdateWindowFrames(WindowFrame frame); [OperationContract(IsOneWay=true)] void WindowHasClosed(IntPtr hwnd); }
渣