Как реализовать прокси-сервера обнаружения
В этом разделе приведены сведения о реализации прокси-сервера обнаружения. Дополнительные сведения о функции обнаружения в Windows Communication Foundation (WCF) см. в обзоре обнаружения WCF. Прокси-сервер обнаружения реализуется созданием класса, расширяющего абстрактный класс DiscoveryProxy. В этом образце определены и использованы несколько других вспомогательных классов. OnResolveAsyncResult
, OnFindAsyncResult
и AsyncResult
. Эти классы реализуют интерфейс IAsyncResult. Дополнительные сведения об IAsyncResult интерфейсе System.IAsyncResult.
В данном разделе реализация прокси-сервера обнаружения разделена на три основные части.
Определение класса, который содержит хранилище данных и расширяет абстрактный класс DiscoveryProxy.
Реализация вспомогательного класса
AsyncResult
.Размещение прокси-сервера обнаружения.
Создание нового проекта консольного приложения
Запустите Visual Studio 2012.
Создайте новый проект консольного приложения. Задайте имя
DiscoveryProxy
для проекта и имяDiscoveryProxyExample
для решения.Добавьте в проект следующие ссылки
System.ServiceModel.dll
System.Servicemodel.Discovery.dll
Внимание
Ссылки должны указывать на версию этих сборок 4.0 или выше.
Реализация класса ProxyDiscoveryService
Добавьте новый файл кода в проект и назовите его DiscoveryProxy.cs.
Добавьте следующие
using
директивы в DiscoveryProxy.cs.using System; using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Discovery; using System.Xml;
Создайте класс
DiscoveryProxyService
, производный от DiscoveryProxy. Примените атрибутServiceBehavior
к классу, как показано в следующем примере.// Implement DiscoveryProxy by extending the DiscoveryProxy class and overriding the abstract methods [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] public class DiscoveryProxyService : DiscoveryProxy { }
Определите в пределах класса
DiscoveryProxy
словарь для хранения зарегистрированных служб.// Repository to store EndpointDiscoveryMetadata. Dictionary<EndpointAddress, EndpointDiscoveryMetadata> onlineServices;
Определите конструктор, который инициализирует словарь.
public DiscoveryProxyService() { this.onlineServices = new Dictionary<EndpointAddress, EndpointDiscoveryMetadata>(); }
Определение методов для обновления кэша прокси-сервера обнаружения
Реализуйте метод
AddOnlineservice
для добавления служб в кэш. Он вызывается каждый раз, когда прокси-сервер получает сообщение объявления.void AddOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata) { lock (this.onlineServices) { this.onlineServices[endpointDiscoveryMetadata.Address] = endpointDiscoveryMetadata; } PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Adding"); }
Реализуйте метод
RemoveOnlineService
, который используется для удаления служб из кэша.void RemoveOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata) { if (endpointDiscoveryMetadata != null) { lock (this.onlineServices) { this.onlineServices.Remove(endpointDiscoveryMetadata.Address); } PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Removing"); } }
Реализуйте методы
MatchFromOnlineService
, которые выполняют сопоставление службы со службой из словаря.void MatchFromOnlineService(FindRequestContext findRequestContext) { lock (this.onlineServices) { foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values) { if (findRequestContext.Criteria.IsMatch(endpointDiscoveryMetadata)) { findRequestContext.AddMatchingEndpoint(endpointDiscoveryMetadata); } } } }
EndpointDiscoveryMetadata MatchFromOnlineService(ResolveCriteria criteria) { EndpointDiscoveryMetadata matchingEndpoint = null; lock (this.onlineServices) { foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values) { if (criteria.Address == endpointDiscoveryMetadata.Address) { matchingEndpoint = endpointDiscoveryMetadata; } } } return matchingEndpoint; }
Реализуйте метод
PrintDiscoveryMetadata
, который выводит пользователю на консоль текстовые данные об операциях прокси-сервера обнаружения.void PrintDiscoveryMetadata(EndpointDiscoveryMetadata endpointDiscoveryMetadata, string verb) { Console.WriteLine("\n**** " + verb + " service of the following type from cache. "); foreach (XmlQualifiedName contractName in endpointDiscoveryMetadata.ContractTypeNames) { Console.WriteLine("** " + contractName.ToString()); break; } Console.WriteLine("**** Operation Completed"); }
Добавьте следующие классы AsyncResult в DiscoveryProxyService. Эти классы позволяют различать результаты асинхронных операций.
sealed class OnOnlineAnnouncementAsyncResult : AsyncResult { public OnOnlineAnnouncementAsyncResult(AsyncCallback callback, object state) : base(callback, state) { this.Complete(true); } public static void End(IAsyncResult result) { AsyncResult.End<OnOnlineAnnouncementAsyncResult>(result); } } sealed class OnOfflineAnnouncementAsyncResult : AsyncResult { public OnOfflineAnnouncementAsyncResult(AsyncCallback callback, object state) : base(callback, state) { this.Complete(true); } public static void End(IAsyncResult result) { AsyncResult.End<OnOfflineAnnouncementAsyncResult>(result); } } sealed class OnFindAsyncResult : AsyncResult { public OnFindAsyncResult(AsyncCallback callback, object state) : base(callback, state) { this.Complete(true); } public static void End(IAsyncResult result) { AsyncResult.End<OnFindAsyncResult>(result); } } sealed class OnResolveAsyncResult : AsyncResult { EndpointDiscoveryMetadata matchingEndpoint; public OnResolveAsyncResult(EndpointDiscoveryMetadata matchingEndpoint, AsyncCallback callback, object state) : base(callback, state) { this.matchingEndpoint = matchingEndpoint; this.Complete(true); } public static EndpointDiscoveryMetadata End(IAsyncResult result) { OnResolveAsyncResult thisPtr = AsyncResult.End<OnResolveAsyncResult>(result); return thisPtr.matchingEndpoint; } }
Определение методов, реализующих функции прокси-сервера обнаружения
Переопределите метод DiscoveryProxy.OnBeginOnlineAnnouncement. Этот метод вызывается, когда прокси-сервер обнаружения получает оперативное сообщение объявления.
// OnBeginOnlineAnnouncement method is called when a Hello message is received by the Proxy protected override IAsyncResult OnBeginOnlineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state) { this.AddOnlineService(endpointDiscoveryMetadata); return new OnOnlineAnnouncementAsyncResult(callback, state); }
Переопределите метод DiscoveryProxy.OnEndOnlineAnnouncement. Этот метод вызывается, когда прокси-сервер обнаружения завершает обработку сообщения объявления.
protected override void OnEndOnlineAnnouncement(IAsyncResult result) { OnOnlineAnnouncementAsyncResult.End(result); }
Переопределите метод DiscoveryProxy.OnBeginOfflineAnnouncement. Этот метод вызывается вместе с получением прокси-сервером обнаружения автономного сообщение объявления.
// OnBeginOfflineAnnouncement method is called when a Bye message is received by the Proxy protected override IAsyncResult OnBeginOfflineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state) { this.RemoveOnlineService(endpointDiscoveryMetadata); return new OnOfflineAnnouncementAsyncResult(callback, state); }
Переопределите метод DiscoveryProxy.OnEndOfflineAnnouncement. Этот метод вызывается, когда прокси-сервер обнаружения завершает обработку автономного сообщения объявления.
protected override void OnEndOfflineAnnouncement(IAsyncResult result) { OnOfflineAnnouncementAsyncResult.End(result); }
Переопределите метод DiscoveryProxy.OnBeginFind. Этот метод вызывается, когда прокси-сервер обнаружения получает запрос поиска.
// OnBeginFind method is called when a Probe request message is received by the Proxy protected override IAsyncResult OnBeginFind(FindRequestContext findRequestContext, AsyncCallback callback, object state) { this.MatchFromOnlineService(findRequestContext); return new OnFindAsyncResult(callback, state); } protected override IAsyncResult OnBeginFind(FindRequest findRequest, AsyncCallback callback, object state) { Collection<EndpointDiscoveryMetadata> matchingEndpoints = MatchFromCache(findRequest.Criteria); return new OnFindAsyncResult( matchingEndpoints, callback, state); }
Переопределите метод DiscoveryProxy.OnEndFind. Этот метод вызывается, когда прокси-сервер обнаружения завершает обработку запроса поиска.
protected override void OnEndFind(IAsyncResult result) { OnFindAsyncResult.End(result); }
Переопределите метод DiscoveryProxy.OnBeginResolve. Этот метод вызывается, когда прокси-сервер обнаружения получает сообщение разрешения.
// OnBeginFind method is called when a Resolve request message is received by the Proxy protected override IAsyncResult OnBeginResolve(ResolveCriteria resolveCriteria, AsyncCallback callback, object state) { return new OnResolveAsyncResult(this.MatchFromOnlineService(resolveCriteria), callback, state); } protected override IAsyncResult OnBeginResolve(ResolveRequest resolveRequest, AsyncCallback callback, object state) { return new OnResolveAsyncResult( this.proxy.MatchFromOnlineService(resolveRequest.Criteria), callback, state); }
Переопределите метод DiscoveryProxy.OnEndResolve. Этот метод вызывается, когда прокси-сервер обнаружения завершает обработку сообщения разрешения.
protected override EndpointDiscoveryMetadata OnEndResolve(IAsyncResult result) { return OnResolveAsyncResult.End(result); }
Методы OnBegin. / OnEnd… обеспечивают логику для последующих операций обнаружения. Например, методы OnBeginFind и OnEndFind реализуют для прокси-сервера обнаружения логику поиска. Когда прокси-сервер обнаружения получает сообщение зонда, эти методы вызываются для отправки ответа клиенту. При необходимости логику поиска можно изменить. Например, можно включить в состав операции поиска поиск по пользовательской области путем анализа XML-метаданных, определяемых алгоритмами или приложениями.
Реализация класса AsyncResult
Определите абстрактный базовый класс AsyncResult. Различные классы асинхронных результатов будут производными от него.
Создайте новый файл кода с именем AsyncResult.cs.
Добавьте следующие
using
директивы в AsyncResult.cs.using System; using System.Threading;
Добавьте следующий класс AsyncResult.
abstract class AsyncResult : IAsyncResult { AsyncCallback callback; bool completedSynchronously; bool endCalled; Exception exception; bool isCompleted; ManualResetEvent manualResetEvent; object state; object thisLock; protected AsyncResult(AsyncCallback callback, object state) { this.callback = callback; this.state = state; this.thisLock = new object(); } public object AsyncState { get { return state; } } public WaitHandle AsyncWaitHandle { get { if (manualResetEvent != null) { return manualResetEvent; } lock (ThisLock) { manualResetEvent ??= new ManualResetEvent(isCompleted); } return manualResetEvent; } } public bool CompletedSynchronously { get { return completedSynchronously; } } public bool IsCompleted { get { return isCompleted; } } object ThisLock { get { return this.thisLock; } } protected static TAsyncResult End<TAsyncResult>(IAsyncResult result) where TAsyncResult : AsyncResult { if (result == null) { throw new ArgumentNullException("result"); } TAsyncResult asyncResult = result as TAsyncResult; if (asyncResult == null) { throw new ArgumentException("Invalid async result.", "result"); } if (asyncResult.endCalled) { throw new InvalidOperationException("Async object already ended."); } asyncResult.endCalled = true; if (!asyncResult.isCompleted) { asyncResult.AsyncWaitHandle.WaitOne(); } if (asyncResult.manualResetEvent != null) { asyncResult.manualResetEvent.Close(); } if (asyncResult.exception != null) { throw asyncResult.exception; } return asyncResult; } protected void Complete(bool completedSynchronously) { if (isCompleted) { throw new InvalidOperationException("This async result is already completed."); } this.completedSynchronously = completedSynchronously; if (completedSynchronously) { this.isCompleted = true; } else { lock (ThisLock) { this.isCompleted = true; if (this.manualResetEvent != null) { this.manualResetEvent.Set(); } } } if (callback != null) { callback(this); } } protected void Complete(bool completedSynchronously, Exception exception) { this.exception = exception; Complete(completedSynchronously); } }
Размещение прокси-сервера обнаружения
Откройте файл Program.cs в проекте DiscoveryProxyExample.
Добавьте следующие
using
директивы.using System; using System.ServiceModel; using System.ServiceModel.Discovery;
В метод
Main()
добавьте следующий код. Он создает экземпляр классаDiscoveryProxy
.Uri probeEndpointAddress = new Uri("net.tcp://localhost:8001/Probe"); Uri announcementEndpointAddress = new Uri("net.tcp://localhost:9021/Announcement"); // Host the DiscoveryProxy service ServiceHost proxyServiceHost = new ServiceHost(new DiscoveryProxyService());
Затем добавьте следующий код, который добавляет конечную точку обнаружения и конечную точку объявления.
try { // Add DiscoveryEndpoint to receive Probe and Resolve messages DiscoveryEndpoint discoveryEndpoint = new DiscoveryEndpoint(new NetTcpBinding(), new EndpointAddress(probeEndpointAddress)); discoveryEndpoint.IsSystemEndpoint = false; // Add AnnouncementEndpoint to receive Hello and Bye announcement messages AnnouncementEndpoint announcementEndpoint = new AnnouncementEndpoint(new NetTcpBinding(), new EndpointAddress(announcementEndpointAddress)); proxyServiceHost.AddServiceEndpoint(discoveryEndpoint); proxyServiceHost.AddServiceEndpoint(announcementEndpoint); proxyServiceHost.Open(); Console.WriteLine("Proxy Service started."); Console.WriteLine(); Console.WriteLine("Press <ENTER> to terminate the service."); Console.WriteLine(); Console.ReadLine(); proxyServiceHost.Close(); } catch (CommunicationException e) { Console.WriteLine(e.Message); } catch (TimeoutException e) { Console.WriteLine(e.Message); } if (proxyServiceHost.State != CommunicationState.Closed) { Console.WriteLine("Aborting the service..."); proxyServiceHost.Abort(); }
Реализация прокси-сервера обнаружения завершена. Перейдите к инструкции. Реализация обнаруживаемой службы, которая регистрируется с помощью прокси-сервера обнаружения.
Пример
Далее приведен полный код, используемый в этом подразделе.
// DiscoveryProxy.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Discovery;
using System.Xml;
namespace Microsoft.Samples.Discovery
{
// Implement DiscoveryProxy by extending the DiscoveryProxy class and overriding the abstract methods
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class DiscoveryProxyService : DiscoveryProxy
{
// Repository to store EndpointDiscoveryMetadata. A database or a flat file could also be used instead.
Dictionary<EndpointAddress, EndpointDiscoveryMetadata> onlineServices;
public DiscoveryProxyService()
{
this.onlineServices = new Dictionary<EndpointAddress, EndpointDiscoveryMetadata>();
}
// OnBeginOnlineAnnouncement method is called when a Hello message is received by the Proxy
protected override IAsyncResult OnBeginOnlineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)
{
this.AddOnlineService(endpointDiscoveryMetadata);
return new OnOnlineAnnouncementAsyncResult(callback, state);
}
protected override void OnEndOnlineAnnouncement(IAsyncResult result)
{
OnOnlineAnnouncementAsyncResult.End(result);
}
// OnBeginOfflineAnnouncement method is called when a Bye message is received by the Proxy
protected override IAsyncResult OnBeginOfflineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)
{
this.RemoveOnlineService(endpointDiscoveryMetadata);
return new OnOfflineAnnouncementAsyncResult(callback, state);
}
protected override void OnEndOfflineAnnouncement(IAsyncResult result)
{
OnOfflineAnnouncementAsyncResult.End(result);
}
// OnBeginFind method is called when a Probe request message is received by the Proxy
protected override IAsyncResult OnBeginFind(FindRequestContext findRequestContext, AsyncCallback callback, object state)
{
this.MatchFromOnlineService(findRequestContext);
return new OnFindAsyncResult(callback, state);
}
protected override void OnEndFind(IAsyncResult result)
{
OnFindAsyncResult.End(result);
}
// OnBeginFind method is called when a Resolve request message is received by the Proxy
protected override IAsyncResult OnBeginResolve(ResolveCriteria resolveCriteria, AsyncCallback callback, object state)
{
return new OnResolveAsyncResult(this.MatchFromOnlineService(resolveCriteria), callback, state);
}
protected override EndpointDiscoveryMetadata OnEndResolve(IAsyncResult result)
{
return OnResolveAsyncResult.End(result);
}
// The following are helper methods required by the Proxy implementation
void AddOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)
{
lock (this.onlineServices)
{
this.onlineServices[endpointDiscoveryMetadata.Address] = endpointDiscoveryMetadata;
}
PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Adding");
}
void RemoveOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)
{
if (endpointDiscoveryMetadata != null)
{
lock (this.onlineServices)
{
this.onlineServices.Remove(endpointDiscoveryMetadata.Address);
}
PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Removing");
}
}
void MatchFromOnlineService(FindRequestContext findRequestContext)
{
lock (this.onlineServices)
{
foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)
{
if (findRequestContext.Criteria.IsMatch(endpointDiscoveryMetadata))
{
findRequestContext.AddMatchingEndpoint(endpointDiscoveryMetadata);
}
}
}
}
EndpointDiscoveryMetadata MatchFromOnlineService(ResolveCriteria criteria)
{
EndpointDiscoveryMetadata matchingEndpoint = null;
lock (this.onlineServices)
{
foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)
{
if (criteria.Address == endpointDiscoveryMetadata.Address)
{
matchingEndpoint = endpointDiscoveryMetadata;
}
}
}
return matchingEndpoint;
}
void PrintDiscoveryMetadata(EndpointDiscoveryMetadata endpointDiscoveryMetadata, string verb)
{
Console.WriteLine("\n**** " + verb + " service of the following type from cache. ");
foreach (XmlQualifiedName contractName in endpointDiscoveryMetadata.ContractTypeNames)
{
Console.WriteLine("** " + contractName.ToString());
break;
}
Console.WriteLine("**** Operation Completed");
}
sealed class OnOnlineAnnouncementAsyncResult : AsyncResult
{
public OnOnlineAnnouncementAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
this.Complete(true);
}
public static void End(IAsyncResult result)
{
AsyncResult.End<OnOnlineAnnouncementAsyncResult>(result);
}
}
sealed class OnOfflineAnnouncementAsyncResult : AsyncResult
{
public OnOfflineAnnouncementAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
this.Complete(true);
}
public static void End(IAsyncResult result)
{
AsyncResult.End<OnOfflineAnnouncementAsyncResult>(result);
}
}
sealed class OnFindAsyncResult : AsyncResult
{
public OnFindAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
this.Complete(true);
}
public static void End(IAsyncResult result)
{
AsyncResult.End<OnFindAsyncResult>(result);
}
}
sealed class OnResolveAsyncResult : AsyncResult
{
EndpointDiscoveryMetadata matchingEndpoint;
public OnResolveAsyncResult(EndpointDiscoveryMetadata matchingEndpoint, AsyncCallback callback, object state)
: base(callback, state)
{
this.matchingEndpoint = matchingEndpoint;
this.Complete(true);
}
public static EndpointDiscoveryMetadata End(IAsyncResult result)
{
OnResolveAsyncResult thisPtr = AsyncResult.End<OnResolveAsyncResult>(result);
return thisPtr.matchingEndpoint;
}
}
}
}
// AsyncResult.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------
using System;
using System.Threading;
namespace Microsoft.Samples.Discovery
{
abstract class AsyncResult : IAsyncResult
{
AsyncCallback callback;
bool completedSynchronously;
bool endCalled;
Exception exception;
bool isCompleted;
ManualResetEvent manualResetEvent;
object state;
object thisLock;
protected AsyncResult(AsyncCallback callback, object state)
{
this.callback = callback;
this.state = state;
this.thisLock = new object();
}
public object AsyncState
{
get
{
return state;
}
}
public WaitHandle AsyncWaitHandle
{
get
{
if (manualResetEvent != null)
{
return manualResetEvent;
}
lock (ThisLock)
{
manualResetEvent ??= new ManualResetEvent(isCompleted);
}
return manualResetEvent;
}
}
public bool CompletedSynchronously
{
get
{
return completedSynchronously;
}
}
public bool IsCompleted
{
get
{
return isCompleted;
}
}
object ThisLock
{
get
{
return this.thisLock;
}
}
protected static TAsyncResult End<TAsyncResult>(IAsyncResult result)
where TAsyncResult : AsyncResult
{
if (result == null)
{
throw new ArgumentNullException("result");
}
TAsyncResult asyncResult = result as TAsyncResult;
if (asyncResult == null)
{
throw new ArgumentException("Invalid async result.", "result");
}
if (asyncResult.endCalled)
{
throw new InvalidOperationException("Async object already ended.");
}
asyncResult.endCalled = true;
if (!asyncResult.isCompleted)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
if (asyncResult.manualResetEvent != null)
{
asyncResult.manualResetEvent.Close();
}
if (asyncResult.exception != null)
{
throw asyncResult.exception;
}
return asyncResult;
}
protected void Complete(bool completedSynchronously)
{
if (isCompleted)
{
throw new InvalidOperationException("This async result is already completed.");
}
this.completedSynchronously = completedSynchronously;
if (completedSynchronously)
{
this.isCompleted = true;
}
else
{
lock (ThisLock)
{
this.isCompleted = true;
if (this.manualResetEvent != null)
{
this.manualResetEvent.Set();
}
}
}
if (callback != null)
{
callback(this);
}
}
protected void Complete(bool completedSynchronously, Exception exception)
{
this.exception = exception;
Complete(completedSynchronously);
}
}
}
// program.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------
using System;
using System.ServiceModel;
using System.ServiceModel.Discovery;
namespace Microsoft.Samples.Discovery
{
class Program
{
public static void Main()
{
Uri probeEndpointAddress = new Uri("net.tcp://localhost:8001/Probe");
Uri announcementEndpointAddress = new Uri("net.tcp://localhost:9021/Announcement");
// Host the DiscoveryProxy service
ServiceHost proxyServiceHost = new ServiceHost(new DiscoveryProxyService());
try
{
// Add DiscoveryEndpoint to receive Probe and Resolve messages
DiscoveryEndpoint discoveryEndpoint = new DiscoveryEndpoint(new NetTcpBinding(), new EndpointAddress(probeEndpointAddress));
discoveryEndpoint.IsSystemEndpoint = false;
// Add AnnouncementEndpoint to receive Hello and Bye announcement messages
AnnouncementEndpoint announcementEndpoint = new AnnouncementEndpoint(new NetTcpBinding(), new EndpointAddress(announcementEndpointAddress));
proxyServiceHost.AddServiceEndpoint(discoveryEndpoint);
proxyServiceHost.AddServiceEndpoint(announcementEndpoint);
proxyServiceHost.Open();
Console.WriteLine("Proxy Service started.");
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate the service.");
Console.WriteLine();
Console.ReadLine();
proxyServiceHost.Close();
}
catch (CommunicationException e)
{
Console.WriteLine(e.Message);
}
catch (TimeoutException e)
{
Console.WriteLine(e.Message);
}
if (proxyServiceHost.State != CommunicationState.Closed)
{
Console.WriteLine("Aborting the service...");
proxyServiceHost.Abort();
}
}
}
}
См. также
- Общие сведения об обнаружении WCF
- Практическое руководство. Реализация обнаруживаемой службы, которая регистрируется в прокси-сервере обнаружения
- Практическое руководство. Реализация клиентского приложения, которое для поиска служб использует прокси-сервер обнаружения
- Практическое руководство. Тестирование прокси-сервера обнаружения