WCF双工nettcp通道未故障

WCF双工nettcp通道未故障,wcf,nettcpbinding,duplex,Wcf,Nettcpbinding,Duplex,问题 我有一个奇怪的问题。我正在控制台应用程序中托管WCF服务器: Console.WriteLine(“按“q”退出”) 它公开了发布和订阅的两个端点(双工绑定) 当我停止或退出console应用程序时,我从未在客户端收到通道故障。我想客户端被告知是服务器关闭。知道这里出了什么问题吗 我只想在console应用程序关闭时引发以下事件之一: msgsvc.InnerDuplexChannel.Faulted += InnerDuplexChannelOnFaulted; msgs

问题

我有一个奇怪的问题。我正在控制台应用程序中托管WCF服务器: Console.WriteLine(“按“q”退出”)

它公开了发布和订阅的两个端点(双工绑定) 当我停止或退出console应用程序时,我从未在客户端收到通道故障。我想客户端被告知是服务器关闭。知道这里出了什么问题吗

我只想在console应用程序关闭时引发以下事件之一:

    msgsvc.InnerDuplexChannel.Faulted += InnerDuplexChannelOnFaulted;
    msgsvc.InnerChannel.Faulted += InnerChannelOnFaulted;
从MSDN:
双工模型不会自动检测服务或客户端何时关闭其通道。因此,如果服务意外终止,默认情况下不会通知服务,或者如果客户端意外终止,则不会通知服务。客户机和服务可以实现它们自己的协议,以便在它们选择的情况下相互通知

AFAIK tcp通道对(持久的)连接问题有很强的响应能力,但您可以使用回调在服务器不可用之前通知客户端。从客户端,您可以使用一些伪ping/poke方法“OnTimer”来获取实际连接状态/保持通道活动。我想,在这一点上恢复客户端代理(重新连接)是很好的。若服务提供元数据端点,则还可以调用svcutil进行尝试连接或以编程方式检索元数据:

  Uri mexAddress = new Uri("http://localhost:5000/myservice");
  var mexClient = new MetadataExchangeClient(mexAddress, MetadataExchangeClientMode.HttpGet);
  MetadataSet metadata = mexClient.GetMetadata();
  MetadataImporter importer = new WsdlImporter(metadata);
  ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();

  ContractDescription description =
  ContractDescription.GetContract(typeof(IMyContract));
  bool contractSupported = endpoints.Any(endpoint =>
  endpoint.Contract.Namespace == description.Namespace &&
  endpoint.Contract.Name == description.Name);


如果您是客户端,并且订阅了所有3个事件,即IClientChannel的关闭、关闭和故障,那么如果您关闭service console应用程序,您至少应该看到关闭和关闭事件。我不知道为什么。如果你正确地关闭,你会认为你会看到错误。我使用的是tcp.net全双工通道,我可以很好地看到这些事件。请记住,这是在2017年,所以从那时起事情可能已经发生了变化,但我在代码中一直依赖这些事件。对于那些说双工模式没有看到频道关闭的人,我不理解。

我知道你的帖子很旧,下面的答案没有回答这个问题。我不确定您在哪里查找这些事件-如果在创建DuplexClient时在DuplexClient中,您是否订阅并传递到您的服务?如果你找到了答案,请把它贴出来。
  Uri mexAddress = new Uri("http://localhost:5000/myservice");
  var mexClient = new MetadataExchangeClient(mexAddress, MetadataExchangeClientMode.HttpGet);
  MetadataSet metadata = mexClient.GetMetadata();
  MetadataImporter importer = new WsdlImporter(metadata);
  ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();

  ContractDescription description =
  ContractDescription.GetContract(typeof(IMyContract));
  bool contractSupported = endpoints.Any(endpoint =>
  endpoint.Contract.Namespace == description.Namespace &&
  endpoint.Contract.Name == description.Name);
ServiceEndpointCollection endpoints = MetadataResolver.Resolve(typeof(IMyContract), mexAddress, MetadataExchangeClientMode.HttpGet)