问题描述
我想要一个发现的服务,将监听所有接口,并公布每个接口发现公告。我希望能够最终使用TCP只配置这在配置文件://0.0.0.0:0 /嗒嗒的服务端点。但是,当我运行下面的code,它发出使用TCP协议的公告://0.0.0.0:0 /等等为这是没用的客户的EndpointAddress
我想收到通知的每个端点是来自于TCP://0.0.0.0:0 /等等,我会preFER使用一个配置文件,而不是一个纲领性的服务主机设置如下图所示。任何想法的一个解决办法?
[TestFixtureSetUp]
公共无效设置()
{
服务1 =新MyContract();
EndpointDiscoveryBehavior discoveryBehavior =新EndpointDiscoveryBehavior();
ServiceDiscoveryBehavior serviceDiscoveryBehavior =新ServiceDiscoveryBehavior(discoveryUri);
serviceDiscoveryBehavior.AnnouncementEndpoints.Add(新UdpAnnouncementEndpoint(announcementUri));
serviceHost1 =新的ServiceHost(服务1,
新的URI [] {新的URI(net.pipe:// localhost的),新的URI(的net.tcp://0.0.0.0:0)});
ServiceEndpoint localEndpoint1 = serviceHost1.AddServiceEndpoint(typeof运算(IContract)
新NetNamedPipeBinding(),
/管);
ServiceEndpoint localEndpoint2 = serviceHost1.AddServiceEndpoint(typeof运算(IContract)
新NetTcpBinding的()
/ TCP);
localEndpoint2.Behaviors.Add(discoveryBehavior);
serviceHost1.Description.Behaviors.Add(serviceDiscoveryBehavior);
serviceHost1.AddServiceEndpoint(新UdpDiscoveryEndpoint(discoveryUri));
serviceHost1.Open();
}
虽然我的解决方案可能不是正确的,严格来说(这应该被固定在WCF本身,如果你问我),它的工作原理,并足以让我的目的。
首先声明一个新的端点的行为,就像这样:
公共类WcfDiscoveryAddressFixEndpointBehavior:IEndpointBehavior,IDispatchMessageInspector
{
公共无效ApplyClientBehavior(ServiceEndpoint终点,ClientRuntime clientRuntime)
{
//附上自己,回复消息的MessageInspectors
clientRuntime.CallbackDispatchRuntime.MessageInspectors.Add(本);
}
公共对象AfterReceiveRequest(参考消息请求,IClientChannel通道的InstanceContext的InstanceContext)
{
对象messageProperty;
如果返回NULL(OperationContext.Current.IncomingMessageProperties.TryGetValue(RemoteEndpointMessageProperty.Name,出messageProperty)!);
VAR remoteEndpointProperty = messageProperty为RemoteEndpointMessageProperty;
如果(remoteEndpointProperty == NULL)返回NULL;
//提取邮件正文
字符串消息体;
使用(VAR oldMessageStream =新的MemoryStream())
{
使用(VAR XW = XmlWriter.Create(oldMessageStream))
{
request.WriteMessage(XW);
xw.Flush();
消息体= Encoding.UTF8.GetString(oldMessageStream.ToArray());
}
}
//替换0.0.0.0实例与实际的远程端点地址
消息体= messageBody.Replace(0.0.0.0,remoteEndpointProperty.Address);
//注意:不要关闭或出售该的MemoryStream的。这将使用WCF的路线。
VAR newMessageStream =新的MemoryStream(Encoding.UTF8.GetBytes(消息体));
XmlDictionaryReader XDR = XmlDictionaryReader.CreateTextReader(newMessageStream,新XmlDictionaryReaderQuotas());
//创建一个新的消息,我们修改端点地址,
//复制了现有的属性和头
消息NewMessage作为= Message.CreateMessage(XDR,int.MaxValue,request.Version);
newMessage.Properties.CopyProperties(request.Properties);
newMessage.Headers.CopyHeadersFrom(request.Headers);
要求= NewMessage作为;
返回null;
}
公共无效BeforeSendReply(参考消息回复,反对correlationState)
{
}
公共无效验证(ServiceEndpoint端点)
{
}
公共无效AddBindingParameters(ServiceEndpoint终点,BindingParameterCollection bindingParameters)
{
}
公共无效ApplyDispatchBehavior(ServiceEndpoint终点,EndpointDispatcher endpointDispatcher)
{
}
}
此终结点行为替换副本原WCF发现应答消息,其中 0.0.0.0
已替换为从中接收邮件的地址,可用的情况下,在 RemoteEndpointMessageProperty
的地址
属性。
要使用它,只需要添加新的端点行为的 UdpDiscoveryEndpoint
当你创建 DiscoveryClient
:
VAR udpDiscoveryEndpoint =新UdpDiscoveryEndpoint();
udpDiscoveryEndpoint.EndpointBehaviors.Add(新WcfDiscoveryAddressFixEndpointBehavior());
_discoveryClient =新DiscoveryClient(udpDiscoveryEndpoint);
//继续像往常一样。
I wanted a discoverable service that would listen on all interfaces and publish discovery announcements for each interface. I was hoping to be able to eventually just configure this in the config file using tcp://0.0.0.0:0/blah as the service endpoint. But when I run the code below, the announcements that it sends out use tcp://0.0.0.0:0/blah as the EndpointAddress which is useless to clients.
I want to receive announcements for every endpoint it derived from tcp://0.0.0.0:0/blah and I would prefer to use a config file and not a programmatic service host setup like below. Any ideas for a workaround?
[TestFixtureSetUp]
public void SetUp()
{
service1 = new MyContract();
EndpointDiscoveryBehavior discoveryBehavior = new EndpointDiscoveryBehavior();
ServiceDiscoveryBehavior serviceDiscoveryBehavior = new ServiceDiscoveryBehavior(discoveryUri);
serviceDiscoveryBehavior.AnnouncementEndpoints.Add(new UdpAnnouncementEndpoint(announcementUri));
serviceHost1 = new ServiceHost(service1,
new Uri[] {new Uri("net.pipe://localhost"), new Uri("net.tcp://0.0.0.0:0")});
ServiceEndpoint localEndpoint1 = serviceHost1.AddServiceEndpoint(typeof (IContract),
new NetNamedPipeBinding(),
"/Pipe");
ServiceEndpoint localEndpoint2 = serviceHost1.AddServiceEndpoint(typeof (IContract),
new NetTcpBinding(),
"/Tcp");
localEndpoint2.Behaviors.Add(discoveryBehavior);
serviceHost1.Description.Behaviors.Add(serviceDiscoveryBehavior);
serviceHost1.AddServiceEndpoint(new UdpDiscoveryEndpoint(discoveryUri));
serviceHost1.Open();
}
While my solution may not be "correct", strictly speaking (this should really be fixed in WCF itself, if you ask me), it works, and is sufficient for my purposes.
First, declare a new endpoint behavior, like so:
public class WcfDiscoveryAddressFixEndpointBehavior : IEndpointBehavior, IDispatchMessageInspector
{
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
// Attach ourselves to the MessageInspectors of reply messages
clientRuntime.CallbackDispatchRuntime.MessageInspectors.Add(this);
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
object messageProperty;
if (!OperationContext.Current.IncomingMessageProperties.TryGetValue(RemoteEndpointMessageProperty.Name, out messageProperty)) return null;
var remoteEndpointProperty = messageProperty as RemoteEndpointMessageProperty;
if (remoteEndpointProperty == null) return null;
// Extract message body
string messageBody;
using (var oldMessageStream = new MemoryStream())
{
using (var xw = XmlWriter.Create(oldMessageStream))
{
request.WriteMessage(xw);
xw.Flush();
messageBody = Encoding.UTF8.GetString(oldMessageStream.ToArray());
}
}
// Replace instances of 0.0.0.0 with actual remote endpoint address
messageBody = messageBody.Replace("0.0.0.0", remoteEndpointProperty.Address);
// NOTE: Do not close or dispose of this MemoryStream. It will be used by WCF down the line.
var newMessageStream = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(newMessageStream, new XmlDictionaryReaderQuotas());
// Create a new message with our modified endpoint address and
// copy over existing properties and headers
Message newMessage = Message.CreateMessage(xdr, int.MaxValue, request.Version);
newMessage.Properties.CopyProperties(request.Properties);
newMessage.Headers.CopyHeadersFrom(request.Headers);
request = newMessage;
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
}
This endpoint behavior replaces the original WCF Discovery reply message with a copy in which instances of 0.0.0.0
have been replaced with the address from which the message was received, available in RemoteEndpointMessageProperty
's Address
property.
To use it, just add the new endpoint behavior to the UdpDiscoveryEndpoint
when you're creating the DiscoveryClient
:
var udpDiscoveryEndpoint = new UdpDiscoveryEndpoint();
udpDiscoveryEndpoint.EndpointBehaviors.Add(new WcfDiscoveryAddressFixEndpointBehavior());
_discoveryClient = new DiscoveryClient(udpDiscoveryEndpoint);
// Proceed as usual.
这篇关于WCF的发现与服务的主机上使用的net.tcp://0.0.0.0:0 /胡说宣布的net.tcp://0.0.0.0:0 /等等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!