8

过去两天我一直在使用 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<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);
}

我觉得我所做的绑定和合同设置应该使它们相同并且我不应该有这个问题(并且应该关闭安全性)。我只是不知道现在该去哪里。

4

1 回答 1

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);
}

马克

于 2009-11-12T18:07:11.810 回答