Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В примере транспорта UDP показано, как реализовать одноадресную рассылку UDP и многоадресную рассылку в качестве настраиваемого транспорта Windows Communication Foundation (WCF). В примере описана рекомендуемая процедура создания пользовательского транспорта в WCF с помощью платформы каналов и рекомендаций WCF. Ниже приведены действия по созданию пользовательского транспорта.
Определите, какие из шаблонов обмена сообщениями канала (IOutputChannel, IInputChannel, IDuplexChannel, IRequestChannel или IReplyChannel) будут поддерживать channelFactory и ChannelListener. Затем определите, будет ли поддерживаться сеансовые варианты этих интерфейсов.
Создайте фабрику каналов и прослушиватель, поддерживающие ваш шаблон обмена сообщениями.
Убедитесь, что все исключения, относящиеся к сети, нормализуются в соответствующий производный класс CommunicationException.
<Добавьте элемент привязки>, который добавляет пользовательский транспорт в стек каналов. Дополнительные сведения см. в разделе "Добавление элемента привязки".
Добавьте раздел расширения элемента привязки, чтобы предоставить новый элемент привязки системе конфигурации.
Добавьте расширения метаданных для обмена данными с другими конечными точками.
Добавьте привязку, которая предварительно настраивает стек элементов привязки в соответствии с хорошо определенным профилем. Дополнительные сведения см. в разделе "Добавление стандартной привязки".
Добавьте раздел привязки и элемент конфигурации привязки, чтобы предоставить привязку системе конфигурации. Дополнительные сведения см. в разделе "Добавление поддержки конфигурации".
Шаблоны Обмена сообщениями
Первым шагом в разработке пользовательского транспорта является определение, какие шаблоны обмена сообщениями (МЭП) требуются для этого транспорта. Доступны три члена Европейского парламента на выбор.
Датаграмма (IInputChannel/IOutputChannel)
При использовании МЕП диаграммы данных клиент отправляет сообщение с помощью обмена "fire and forget". Обмен типа «отправил и забыл» — это тот, который требует подтверждения успешной доставки. Сообщение может быть потеряно при передаче и никогда не дойдет до службы. Если операция отправки успешно завершается на стороне клиента, это не гарантирует, что удаленная конечная точка получила сообщение. Диаграмма данных — это базовый стандартный блок для обмена сообщениями, так как вы можете создавать собственные протоколы на его основе, включая надежные протоколы и безопасные протоколы. Каналы датаграмм клиента реализуют IOutputChannel интерфейс, а каналы датаграмм службы реализуют IInputChannel интерфейс.
Request-Response (IRequestChannel/IReplyChannel)
В этом MEP отправляется сообщение, и получен ответ. Шаблон состоит из пар запросов-ответов. Примерами вызовов типа 'запрос-ответ' являются удаленные вызовы процедур (RPC) и запросы GET браузера. Этот шаблон также называется полудуплексным. В этом MEP клиентские каналы реализуют IRequestChannel, а каналы обслуживания используют IReplyChannel.
Дуплекс (IDuplexChannel)
Механизм обмена сообщениями (дуплексный MEP) позволяет клиенту отправить произвольное количество сообщений, которые могут быть получены в любом порядке. Дуплексный MEP похож на телефонный разговор, где каждое произнесённое слово является сообщением. Так как обе стороны могут отправлять и получать в этом MEP, интерфейс, реализованный клиентскими и сервисными каналами IDuplexChannel.
Каждый из этих членов Европарламента также может поддерживать заседания. Добавленная функция, предоставляемая каналом с поддержкой сеансов, заключается в том, что она сопоставляет все сообщения, отправленные и полученные на канале. Шаблон Request-Response является автономным сеансом двух сообщений, так как запрос и ответ коррелируются. В отличие от этого, шаблон Request-Response, поддерживающий сеансы, подразумевает, что все пары запросов и ответов в этом канале коррелируются друг с другом. Это дает вам в общей сложности шесть МЭП — датаграмма, запрос-ответ, дуплекс, датаграмма с сеансами, Request-Response с сеансами и дуплекс с сеансами — из которых можно выбирать.
Замечание
Для транспорта UDP единственный поддерживаемый MEP является Datagram, так как UDP является по сути протоколом "fire and forget".
Жизненный цикл объектов ICommunicationObject и WCF
WCF имеет общий компьютер состояния, используемый для управления жизненным циклом объектов, таких как IChannel, IChannelFactoryи IChannelListener используемых для обмена данными. Существует пять состояний, в которых эти объекты связи могут существовать. Эти состояния представлены CommunicationState перечислением и представлены следующим образом:
Создано: это состояние ICommunicationObject, когда оно впервые создается. В этом состоянии не происходит ввода/вывода (I/O).
Открытие: объекты переходят в это состояние, когда вызывается Open. На этом этапе свойства становятся неизменяемыми, и начинается ввод и вывод данных. Этот переход действителен только из состояния "Создано".
Открыто: объекты переходили к этому состоянию при завершении открытого процесса. Этот переход действителен только из состояния 'Открыто'. На этом этапе объект полностью доступен для передачи.
Закрытие: объекты переходят в это состояние при вызове Close для корректного завершения работы. Этот переход действителен только из открытого состояния.
Закрыто: в закрытом состоянии объекты больше не используются. Как правило, большая часть конфигурации по-прежнему доступна для проверки, но связь не может произойти. Это состояние эквивалентно удалению.
Сбой. В состоянии сбоя объекты доступны для проверки, но больше не доступны. При возникновении ошибки, невосстановимой, объект переходит в это состояние. Допустимый переход из этого состояния возможен только в состояние
Closed
.
Существуют события, которые активируются на каждый переход состояния. Метод Abort можно вызывать в любое время, и он переводит объект немедленно из его текущего состояния в состояние "Закрыто". Вызов Abort завершает все незавершенные работы.
Фабрика каналов и прослушиватель каналов
Следующим шагом написания пользовательского транспорта является создание реализации клиентских IChannelFactory каналов и IChannelListener каналов обслуживания. Слой каналов использует шаблон фабрики для создания каналов. WCF предоставляет вспомогательные средства базового класса для этого процесса.
Класс CommunicationObject реализует ICommunicationObject и применяет компьютер состояния, описанный ранее на шаге 2.
Класс ChannelManagerBase реализует CommunicationObject и предоставляет единый базовый класс для ChannelFactoryBase и ChannelListenerBase. Класс ChannelManagerBase работает в сочетании с ChannelBase, который является базовым классом, реализующим IChannel.
Класс ChannelFactoryBase реализует ChannelManagerBase и IChannelFactory, и объединяет
CreateChannel
перегрузки в одинOnCreateChannel
абстрактный метод.Класс ChannelListenerBase реализует IChannelListener. Он осуществляет базовое управление состоянием.
В этом примере реализация фабрики содержится в UdpChannelFactory.cs, а реализация прослушивателя содержится в UdpChannelListener.cs. Реализации IChannel находятся в UdpOutputChannel.cs и UdpInputChannel.cs.
Фабрика каналов UDP
Производное UdpChannelFactory
происходит от ChannelFactoryBase. Пример переопределяет GetProperty для обеспечения доступа к версии кодировщика сообщений. Этот пример также переопределяет OnClose, чтобы мы могли уничтожить наш экземпляр BufferManager при переходе автомата состояний.
Выходной канал UDP
UdpOutputChannel
реализует IOutputChannel. Конструктор проверяет аргументы и создает целевой EndPoint объект на EndpointAddress основе переданного объекта.
this.socket = new Socket(this.remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
Канал может быть закрыт грациозно или неграциозно. Если канал закрыт корректно, сокет закрывается, и вызов выполняется к методу базового класса OnClose
. Если это вызывает исключение, инфраструктура вызывает Abort
для обеспечения очистки канала.
this.socket.Close(0);
Затем мы реализуем Send()
и BeginSend()
/EndSend()
. Это разбивается на два основных раздела. Сначала мы сериализируем сообщение в массив байтов.
ArraySegment<byte> messageBuffer = EncodeMessage(message);
Затем мы отправим полученные данные по проводу.
this.socket.SendTo(messageBuffer.Array, messageBuffer.Offset, messageBuffer.Count, SocketFlags.None, this.remoteEndPoint);
The UdpChannelListener
Реализованный пример UdpChannelListener
наследуется от класса ChannelListenerBase. Он использует один сокет UDP для получения диаграмм данных. Метод OnOpen
получает данные с помощью сокета UDP в асинхронном цикле. Затем данные преобразуются в сообщения с помощью платформы кодирования сообщений.
message = MessageEncoderFactory.Encoder.ReadMessage(new ArraySegment<byte>(buffer, 0, count), bufferManager);
Так как один и тот же канал данных представляет сообщения, поступающие из ряда источников, UdpChannelListener
это одноэлементный прослушиватель. В одно и то же время может быть не более одной активной IChannel, связанной с этим прослушивателем. Пример создает еще один, только если канал, возвращаемый AcceptChannel
методом, впоследствии удаляется. При получении сообщения оно помещается в очередь в этот единственный канал.
КаналВводаUDP
Класс UdpInputChannel
реализует IInputChannel
. Он состоит из очереди входящих сообщений, заполненных сокетом UdpChannelListener
. Эти сообщения извлекаются методом IInputChannel.Receive
.
Добавление элемента привязки
Теперь, когда фабрики и каналы созданы, их необходимо предоставить среде выполнения ServiceModel через привязку. Привязка — это коллекция элементов привязки, представляющих стек связи, связанный с адресом службы. Каждый элемент в стеке представлен элементом <привязки> .
В данном примере элемент привязки — это UdpTransportBindingElement
, который является производным от TransportBindingElement. Он переопределяет следующие методы для создания фабрик, связанных с нашей привязкой.
public IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
return (IChannelFactory<TChannel>)(object)new UdpChannelFactory(this, context);
}
public IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
return (IChannelListener<TChannel>)(object)new UdpChannelListener(this, context);
}
Он также содержит элементы для клонирования BindingElement
и возврата нашей схемы (soap.udp).
Добавление поддержки метаданных к элементу привязки транспорта
Чтобы интегрировать транспорт в систему метаданных, необходимо поддерживать как импорт, так и экспорт политики. Это позволяет создавать клиенты нашей привязки с помощью средства служебной программы метаданных ServiceModel (Svcutil.exe).
Добавление поддержки WSDL
Элемент транспортной привязки в привязке отвечает за экспорт и импорт информации об адресации в метаданных. При использовании привязки SOAP элемент привязки транспорта также должен экспортировать правильный URI транспорта в метаданных.
Экспорт WSDL
Для экспорта сведений об адресации UdpTransportBindingElement
реализует интерфейс IWsdlExportExtension
. Метод ExportEndpoint
добавляет правильные сведения об адресации в порт WSDL.
if (context.WsdlPort != null)
{
AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);
}
Реализация UdpTransportBindingElement
ExportEndpoint
метода также экспортирует URI транспорта, когда конечная точка использует привязку SOAP.
WsdlNS.SoapBinding soapBinding = GetSoapBinding(context, exporter);
if (soapBinding != null)
{
soapBinding.Transport = UdpPolicyStrings.UdpNamespace;
}
Импорт WSDL
Чтобы расширить систему импорта WSDL для обработки импорта адресов, необходимо добавить следующую конфигурацию в файл конфигурации для Svcutil.exe, как показано в файле Svcutil.exe.config.
<configuration>
<system.serviceModel>
<client>
<metadata>
<policyImporters>
<extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
При запуске Svcutil.exeсуществует два варианта получения Svcutil.exe для загрузки расширений импорта WSDL:
Укажите Svcutil.exe на наш файл конфигурации, используя /SvcutilConfig:<file>.
Добавьте раздел конфигурации в Svcutil.exe.config в том же каталоге, что и Svcutil.exe.
Тип UdpBindingElementImporter
реализует IWsdlImportExtension
интерфейс. Метод ImportEndpoint
импортирует адрес из порта WSDL.
BindingElementCollection bindingElements = context.Endpoint.Binding.CreateBindingElements();
TransportBindingElement transportBindingElement = bindingElements.Find<TransportBindingElement>();
if (transportBindingElement is UdpTransportBindingElement)
{
ImportAddress(context);
}
Добавление поддержки политик
Элемент пользовательской привязки может выводить утверждения политики в привязке WSDL для служебной конечной точки, чтобы выразить возможности этого элемента привязки.
Экспорт политики
Тип UdpTransportBindingElement
реализует IPolicyExportExtension
для предоставления поддержки экспорта политик. В результате System.ServiceModel.MetadataExporter
UdpTransportBindingElement
интегрируется в формирование политики для любой привязки, содержащей UdpTransportBindingElement
.
В IPolicyExportExtension.ExportPolicy
мы добавляем утверждение для UDP и другое утверждение, если мы находимся в режиме многоадресной рассылки. Это связано с тем, что режим мультикаста влияет на способ построения стека связи и, следовательно, должен быть согласован между обеими сторонами.
ICollection<XmlElement> bindingAssertions = context.GetBindingAssertions();
XmlDocument xmlDocument = new XmlDocument();
bindingAssertions.Add(xmlDocument.CreateElement(
UdpPolicyStrings.Prefix, UdpPolicyStrings.TransportAssertion, UdpPolicyStrings.UdpNamespace));
if (Multicast)
{
bindingAssertions.Add(xmlDocument.CreateElement(
UdpPolicyStrings.Prefix,
UdpPolicyStrings.MulticastAssertion,
UdpPolicyStrings.UdpNamespace));
}
Поскольку элементы пользовательской транспортной привязки отвечают за обработку адресации, реализация IPolicyExportExtension
на UdpTransportBindingElement
также должна обеспечивать экспорт соответствующих политических утверждений WS-Addressing, чтобы указать версию используемой WS-Addressing.
AddWSAddressingAssertion(context, encodingBindingElement.MessageVersion.Addressing);
Импорт политики
Чтобы расширить систему импорта политик, необходимо добавить следующую конфигурацию в файл конфигурации для Svcutil.exe, как показано в файле Svcutil.exe.config.
<configuration>
<system.serviceModel>
<client>
<metadata>
<policyImporters>
<extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
Затем мы реализуем IPolicyImporterExtension
из зарегистрированного класса (UdpBindingElementImporter
). В ImportPolicy()
этом разделе мы рассмотрим утверждения в нашем пространстве имен и обработаем их для создания транспорта и проверяем, является ли он многоадресной рассылкой. Мы также должны удалить утверждения, которые мы обрабатываем, из списка связанных утверждений. Опять же, при запуске Svcutil.exeсуществует два варианта интеграции:
Укажите Svcutil.exe на наш файл конфигурации, используя /SvcutilConfig:<file>.
Добавьте раздел конфигурации в Svcutil.exe.config в том же каталоге, что и Svcutil.exe.
Добавление стандартной привязки
Элемент привязки можно использовать следующими способами:
С помощью пользовательской привязки: пользователь может создать собственную привязку на основе произвольного набора элементов привязки.
Используя привязку, которую предоставляет система и которая включает наш элемент привязки. WCF предоставляет ряд системных привязок, таких как
BasicHttpBinding
,NetTcpBinding
иWsHttpBinding
. Каждая из этих привязок связана с хорошо определенным профилем.
В примере реализована привязка профиля в SampleProfileUdpBinding
, которая наследуется от Binding. Содержит SampleProfileUdpBinding
до четырех элементов привязки в нем: UdpTransportBindingElement
, TextMessageEncodingBindingElement CompositeDuplexBindingElement
и ReliableSessionBindingElement
.
public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingElements = new BindingElementCollection();
if (ReliableSessionEnabled)
{
bindingElements.Add(session);
bindingElements.Add(compositeDuplex);
}
bindingElements.Add(encoding);
bindingElements.Add(transport);
return bindingElements.Clone();
}
Добавление пользовательского средства импорта стандартных привязок
Svcutil.exe и WsdlImporter
тип по умолчанию распознает и импортирует системные привязки. В противном случае связывание импортируется в виде экземпляра CustomBinding
. Чтобы задействовать Svcutil.exe и WsdlImporter
, SampleProfileUdpBinding
и UdpBindingElementImporter
также действуют как пользовательские импортеры стандартных привязок.
Пользовательский импортер стандартных привязок реализует ImportEndpoint
метод в IWsdlImportExtension
интерфейсе, чтобы проверить CustomBinding
экземпляр, импортированный из метаданных, чтобы узнать, может ли он быть создан определенной стандартной привязкой.
if (context.Endpoint.Binding is CustomBinding)
{
Binding binding;
if (transportBindingElement is UdpTransportBindingElement)
{
//if TryCreate is true, the CustomBinding will be replace by a SampleProfileUdpBinding in the
//generated config file for better typed generation.
if (SampleProfileUdpBinding.TryCreate(bindingElements, out binding))
{
binding.Name = context.Endpoint.Binding.Name;
binding.Namespace = context.Endpoint.Binding.Namespace;
context.Endpoint.Binding = binding;
}
}
}
Как правило, реализация пользовательского средства импорта стандартных привязок включает проверку свойств импортированных элементов привязки, чтобы убедиться, что изменены только свойства, которые могут быть заданы стандартной привязкой, и все остальные свойства являются их значениями по умолчанию. Базовая стратегия реализации средства импорта стандартных привязок заключается в создании экземпляра стандартной привязки, распространении свойств из элементов привязки к экземпляру стандартной привязки, который поддерживает стандартная привязка, и сравнения элементов привязки из стандартной привязки с импортированными элементами привязки.
Добавление поддержки конфигурации
Чтобы обеспечить доступ к нашему транспорту с помощью конфигурации, необходимо имплементировать два раздела конфигурации. Первое — это BindingElementExtensionElement
для UdpTransportBindingElement
. Это позволяет CustomBinding
реализации ссылаться на наш элемент привязки. Второй — Configuration
для наших SampleProfileUdpBinding
.
Элемент Расширения Связывания
Этот раздел UdpTransportElement
является BindingElementExtensionElement
, который открывает UdpTransportBindingElement
для системы конфигурации. С помощью нескольких основных переопределений мы определяем имя нашего раздела конфигурации, тип элемента привязки и то, как создать наш элемент привязки. Затем мы можем зарегистрировать раздел расширения в файле конфигурации, как показано в следующем коде.
<configuration>
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="udpTransport" type="Microsoft.ServiceModel.Samples.UdpTransportElement, UdpTransport" />
</bindingElementExtensions>
</extensions>
</system.serviceModel>
</configuration>
Расширение можно использовать в пользовательских привязках для применения UDP в качестве транспорта.
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding configurationName="UdpCustomBinding">
<udpTransport/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
Раздел соединения
Этот раздел SampleProfileUdpBindingCollectionElement
является StandardBindingCollectionElement
, который открывает SampleProfileUdpBinding
для системы конфигурации. Основная реализация делегируется SampleProfileUdpBindingConfigurationElement
, который происходит от StandardBindingElement
. У SampleProfileUdpBindingConfigurationElement
есть свойства, которые соответствуют свойствам на SampleProfileUdpBinding
, а также функции для отображения из привязки ConfigurationElement
. Наконец, переопределите OnApplyConfiguration
метод в нашем SampleProfileUdpBinding
, как показано в следующем коде.
protected override void OnApplyConfiguration(string configurationName)
{
if (binding == null)
throw new ArgumentNullException("binding");
if (binding.GetType() != typeof(SampleProfileUdpBinding))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
"Invalid type for binding. Expected type: {0}. Type passed in: {1}.",
typeof(SampleProfileUdpBinding).AssemblyQualifiedName,
binding.GetType().AssemblyQualifiedName));
}
SampleProfileUdpBinding udpBinding = (SampleProfileUdpBinding)binding;
udpBinding.OrderedSession = this.OrderedSession;
udpBinding.ReliableSessionEnabled = this.ReliableSessionEnabled;
udpBinding.SessionInactivityTimeout = this.SessionInactivityTimeout;
if (this.ClientBaseAddress != null)
udpBinding.ClientBaseAddress = ClientBaseAddress;
}
Чтобы зарегистрировать этот обработчик в системе конфигурации, добавьте следующий раздел в соответствующий файл конфигурации.
<configuration>
<configSections>
<sectionGroup name="system.serviceModel">
<sectionGroup name="bindings">
<section name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />
</sectionGroup>
</sectionGroup>
</configSections>
</configuration>
Затем можно ссылаться на него из раздела конфигурации serviceModel.
<configuration>
<system.serviceModel>
<client>
<endpoint configurationName="calculator"
address="soap.udp://localhost:8001/"
bindingConfiguration="CalculatorServer"
binding="sampleProfileUdpBinding"
contract= "Microsoft.ServiceModel.Samples.ICalculatorContract">
</endpoint>
</client>
</system.serviceModel>
</configuration>
Тестовая служба и клиент UDP
Код теста для использования этого примера транспорта доступен в каталогах UdpTestService и UdpTestClient. Код службы состоит из двух тестов— один тест настраивает привязки и конечные точки из кода, а другой — с помощью конфигурации. Оба теста используют две конечные точки. Одна конечная точка использует SampleUdpProfileBinding
с установленным <reliableSession> на true
. Другая конечная точка использует пользовательскую привязку с UdpTransportBindingElement
. Это эквивалентно использованию SampleUdpProfileBinding
с <параметром reliableSession>, установленным на false
. Оба теста создают службу, добавляют конечную точку для каждой привязки, открывают службу, а затем нужно будет подождать, пока пользователь не нажмет клавишу ВВОД, перед тем как закрыть службу.
При запуске тестового приложения службы вы увидите следующие выходные данные.
Testing Udp From Code.
Service is started from code...
Press <ENTER> to terminate the service and start service from config...
Затем можно запустить тестовое клиентское приложение для опубликованных конечных точек. Тестовое приложение клиента создает клиент для каждой конечной точки и отправляет пять сообщений в каждую конечную точку. Следующий вывод находится на стороне клиента.
Testing Udp From Imported Files Generated By SvcUtil.
0
3
6
9
12
Press <ENTER> to complete test.
Ниже приведены полные выходные данные службы.
Service is started from code...
Press <ENTER> to terminate the service and start service from config...
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
adding 0 + 0
adding 1 + 2
adding 2 + 4
adding 3 + 6
adding 4 + 8
Чтобы запустить клиентское приложение для конечных точек, опубликованных с помощью конфигурации, выберите сервис и нажмите клавишу ВВОД, а затем снова запустите тестовый клиент. В службе должны появиться следующие выходные данные.
Testing Udp From Config.
Service is started from config...
Press <ENTER> to terminate the service and exit...
Выполнение клиента снова дает те же результаты, что и ранее.
Чтобы повторно создать клиентский код и конфигурацию с помощью Svcutil.exe, запустите служебное приложение, а затем выполните следующую команду Svcutil.exe из корневого каталога примера.
svcutil http://localhost:8000/udpsample/ /reference:UdpTransport\bin\UdpTransport.dll /svcutilConfig:svcutil.exe.config
Обратите внимание, что Svcutil.exe не создает конфигурацию расширения привязки для SampleProfileUdpBinding
, поэтому ее необходимо добавить вручную.
<configuration>
<system.serviceModel>
<extensions>
<!-- This was added manually because svcutil.exe does not add this extension to the file -->
<bindingExtensions>
<add name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />
</bindingExtensions>
</extensions>
</system.serviceModel>
</configuration>
Настройка, сборка и запуск примера
Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.
Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в запуска примеров Windows Communication Foundation.
См. предыдущий раздел "Служба тестирования UDP и клиент".