过去两天我一直在与WCF合作,而且我的开发机器上的服务器和客户端都很顺利。既然我正试图在网络上的另一台机器上与客户端进行一些分布式测试,我就开始遇到问题了。现在我得到的错误是:
由于EndpointDispatcher上的ContractFilter不匹配,无法在接收方处理带有操作“http://tempuri.org/IWindowUpdateContract/UpdateWindowFrames”的消息。这可能是由于合同不匹配(发送方与接收方之间的操作不匹配)或发送方与接收方之间的绑定/安全性不匹配。检查发件人和收件人是否具有相同的合同和相同的约束(包括安全要求,例如邮件,传输,无)。
由于这已经是一次大规模的学习经历(我之前没有做任何远程处理,RPC等)我想继续开发学习工具并在我完成时重新考虑安全性(我无意构建任何东西)在没有适当的安全最佳实践的情况下实际使用它。)
注意:
我的服务器是这样创建的:
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<IUserInputContract>(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);
}
我觉得我所做的绑定和合同设置应该使它们完全相同,我不应该有这个问题(应该关闭安全性)。我现在不知道该去哪里。
答案 0 :(得分:10)
我同意你的观点 - 似乎服务器和客户端的安全设置都是相同的。
旁边的注释:一旦你这样做:
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);
}
马克