Transporte: UDP
O exemplo de Transporte UDP demonstra como implementar UDP unicast e multicast como um transporte personalizado do Windows Communication Foundation (WCF). O exemplo descreve o procedimento recomendado para criar um transporte personalizado no WCF, usando a estrutura de canal e seguindo as práticas recomendadas do WCF. As etapas para criar um transporte personalizado são as seguintes:
Decida qual dos padrões de troca de mensagens do canal (IOutputChannel, IInputChannel, IDuplexChannel, IRequestChannel ou IReplyChannel) seu ChannelFactory e ChannelListener suportarão. Em seguida, decida se você suportará as variações de sessão dessas interfaces.
Crie uma fábrica de canais e um ouvinte que suportem seu padrão de troca de mensagens.
Certifique-se de que todas as exceções específicas da rede sejam normalizadas para a classe derivada apropriada de CommunicationException.
Adicione um <elemento binding> que adiciona o transporte personalizado a uma pilha de canais. Para obter mais informações, consulte Adicionando um elemento de vinculação.
Adicione uma seção de extensão de elemento de vinculação para expor o novo elemento de vinculação ao sistema de configuração.
Adicione extensões de metadados para comunicar recursos a outros pontos de extremidade.
Adicione uma associação que pré-configure uma pilha de elementos de vinculação de acordo com um perfil bem definido. Para obter mais informações, consulte Adicionando uma ligação padrão.
Adicione uma seção de vinculação e um elemento de configuração de vinculação para expor a associação ao sistema de configuração. Para obter mais informações, consulte Adicionando suporte à configuração.
Padrões de troca de mensagens
A primeira etapa para escrever um transporte personalizado é decidir quais padrões de troca de mensagens (MEPs) são necessários para o transporte. Há três deputados ao Parlamento Europeu à escolha:
Datagrama (IInputChannel/IOutputChannel)
Ao usar um MEP de datagrama, um cliente envia uma mensagem usando uma troca "disparar e esquecer". Uma troca de fogo e esquecimento é aquela que requer confirmação fora da banda de entrega bem-sucedida. A mensagem pode ser perdida em trânsito e nunca chegar ao serviço. Se a operação de envio for concluída com êxito no final do cliente, isso não garante que o ponto de extremidade remoto tenha recebido a mensagem. O datagrama é um bloco de construção fundamental para mensagens, pois você pode criar seus próprios protocolos sobre ele, incluindo protocolos confiáveis e protocolos seguros. Os canais de datagrama do cliente implementam a interface e os IOutputChannel canais de datagrama de serviço implementam a IInputChannel interface.
Solicitação-Resposta (IRequestChannel/IReplyChannel)
Neste deputado, é enviada uma mensagem e recebida uma resposta. O padrão consiste em pares solicitação-resposta. Exemplos de chamadas de solicitação-resposta são chamadas de procedimento remoto (RPC) e GETs do navegador. Este padrão também é conhecido como Half-Duplex. Neste MEP, os canais do cliente implementam IRequestChannel e os canais de atendimento implementam IReplyChannel.
Duplex (IDuplexChannel)
O duplex MEP permite que um número arbitrário de mensagens sejam enviadas por um cliente e recebidas em qualquer ordem. O MEP duplex é como uma conversa telefónica, em que cada palavra dita é uma mensagem. Como ambos os lados podem enviar e receber neste MEP, a interface implementada pelo cliente e canais de atendimento é IDuplexChannel.
Cada um destes deputados também pode apoiar as sessões. A funcionalidade adicional fornecida por um canal com reconhecimento de sessão é que ele correlaciona todas as mensagens enviadas e recebidas em um canal. O padrão Request-Response é uma sessão autônoma de duas mensagens, pois a solicitação e a resposta estão correlacionadas. Por outro lado, o padrão Solicitação-Resposta que suporta sessões implica que todos os pares de solicitação/resposta nesse canal estão correlacionados entre si. Isso oferece um total de seis MEPs — Datagrama, Solicitação-Resposta, Duplex, Datagrama com sessões, Solicitação-Resposta com sessões e Duplex com sessões — para escolher.
Nota
Para o transporte UDP, o único MEP suportado é o Datagram, porque o UDP é inerentemente um protocolo "fire and forget".
O ICommunicationObject e o ciclo de vida do objeto WCF
O WCF tem uma máquina de estado comum que é usada para gerenciar o ciclo de vida de objetos como IChannel, IChannelFactorye IChannelListener que são usados para comunicação. Há cinco estados em que esses objetos de comunicação podem existir. Esses estados são representados pela CommunicationState enumeração e são os seguintes:
Criado: Este é o estado de a ICommunicationObject quando ele é instanciado pela primeira vez. Nenhuma entrada/saída (E/S) ocorre nesse estado.
Abertura: Os objetos transitam para este estado quando Open são chamados. Neste ponto, as propriedades tornam-se imutáveis e a entrada/saída pode começar. Essa transição é válida somente a partir do estado Criado.
Aberto: os objetos transitam para esse estado quando o processo aberto é concluído. Essa transição é válida somente a partir do estado Abertura. Neste ponto, o objeto é totalmente utilizável para transferência.
Fechamento: Os objetos transitam para esse estado quando Close é chamado para um desligamento normal. Essa transição é válida somente a partir do estado Aberto.
Fechado: No estado Fechado, os objetos não são mais utilizáveis. Em geral, a maioria das configurações ainda está acessível para inspeção, mas nenhuma comunicação pode ocorrer. Este estado equivale a ser descartado.
Com defeito: no estado com defeito, os objetos são acessíveis à inspeção, mas não são mais utilizáveis. Quando ocorre um erro não recuperável, o objeto transita para esse estado. A única transição válida deste estado é para o
Closed
estado.
Há eventos que disparam para cada transição de estado. O Abort método pode ser chamado a qualquer momento e faz com que o objeto faça a transição imediata de seu estado atual para o estado Fechado. A chamada Abort encerra qualquer trabalho inacabado.
Fábrica de canais e ouvinte de canais
O próximo passo para escrever um transporte personalizado é criar uma implementação de para canais de cliente e de para canais de IChannelFactoryIChannelListener serviço. A camada de canal usa um padrão de fábrica para construir canais. O WCF fornece auxiliares de classe base para esse processo.
A CommunicationObject classe implementa ICommunicationObject e impõe a máquina de estado descrita anteriormente na Etapa 2.
A ChannelManagerBase classe implementa CommunicationObject e fornece uma classe base unificada para ChannelFactoryBase e ChannelListenerBase. A ChannelManagerBase classe trabalha em conjunto com ChannelBase, que é uma classe base que implementa IChannelo .
A ChannelFactoryBase classe implementa ChannelManagerBase e IChannelFactory consolida as
CreateChannel
sobrecargas em umOnCreateChannel
método abstrato.A ChannelListenerBase classe implementa IChannelListener. Cuida da gestão básica do Estado.
Neste exemplo, a implementação de fábrica está contida em UdpChannelFactory.cs e a implementação de ouvinte está contida em UdpChannelListener.cs. As IChannel implementações estão em UdpOutputChannel.cs e UdpInputChannel.cs.
A fábrica de canais UDP
O UdpChannelFactory
deriva de ChannelFactoryBase. O exemplo substitui GetProperty para fornecer acesso à versão da mensagem do codificador de mensagens. O exemplo também substitui OnClose para que possamos derrubar nossa instância de quando a máquina de BufferManager estado faz a transição.
O canal de saída UDP
Os UdpOutputChannel
implementos IOutputChannel. O construtor valida os argumentos e constrói um objeto de destino EndPoint com base no EndpointAddress que é passado.
this.socket = new Socket(this.remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
O canal pode ser fechado graciosamente ou sem graça. Se o canal estiver fechado normalmente, o soquete será fechado e uma chamada será feita para o método de classe OnClose
base. Se isso gerar uma exceção, a infraestrutura chamará Abort
para garantir que o canal seja limpo.
this.socket.Close(0);
Em seguida, implementamos Send()
e BeginSend()
/EndSend()
. Esta divide-se em duas secções principais. Primeiro, serializamos a mensagem em uma matriz de bytes.
ArraySegment<byte> messageBuffer = EncodeMessage(message);
Em seguida, enviamos os dados resultantes no fio.
this.socket.SendTo(messageBuffer.Array, messageBuffer.Offset, messageBuffer.Count, SocketFlags.None, this.remoteEndPoint);
O UdpChannelListener
O UdpChannelListener
que o exemplo implementa deriva da ChannelListenerBase classe. Ele usa um único soquete UDP para receber datagramas. O OnOpen
método recebe dados usando o soquete UDP em um loop assíncrono. Os dados são então convertidos em mensagens usando o Message Encoding Framework.
message = MessageEncoderFactory.Encoder.ReadMessage(new ArraySegment<byte>(buffer, 0, count), bufferManager);
Como o mesmo canal de datagrama representa mensagens que chegam de várias fontes, o UdpChannelListener
é um ouvinte singleton. Há, no máximo, um ativo IChannel associado a esse ouvinte de cada vez. A amostra gera outra somente se um canal que é retornado pelo AcceptChannel
método é posteriormente descartado. Quando uma mensagem é recebida, ela é enfileirada nesse canal singleton.
UdpInputChannel
A UdpInputChannel
classe implementa IInputChannel
. Ele consiste em uma fila de mensagens de entrada que é preenchida pelo soquete UdpChannelListener
do . Essas mensagens são retiradas da IInputChannel.Receive
fila pelo método.
Adicionando um elemento de vinculação
Agora que as fábricas e os canais são construídos, devemos expô-los ao tempo de execução do ServiceModel por meio de uma ligação. Uma associação é uma coleção de elementos de ligação que representa a pilha de comunicação associada a um endereço de serviço. Cada elemento na pilha é representado por um <elemento de ligação> .
Na amostra, o elemento de ligação é UdpTransportBindingElement
, que deriva de TransportBindingElement. Ele substitui os seguintes métodos para construir as fábricas associadas à nossa vinculação.
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);
}
Ele também contém membros para clonar e retornar nosso BindingElement
esquema (soap.udp).
Adicionando suporte a metadados para um elemento de vinculação de transporte
Para integrar o nosso transporte no sistema de metadados, temos de apoiar tanto a importação como a exportação de políticas. Isso nos permite gerar clientes de nossa vinculação por meio da ServiceModel Metadata Utility Tool (Svcutil.exe).
Adicionando suporte a WSDL
O elemento de ligação de transporte em uma associação é responsável por exportar e importar informações de endereçamento em metadados. Ao usar uma associação SOAP, o elemento de ligação de transporte também deve exportar um URI de transporte correto nos metadados.
Exportação WSDL
Para exportar informações de endereçamento, o UdpTransportBindingElement
implementa a IWsdlExportExtension
interface. O ExportEndpoint
método adiciona as informações de endereçamento corretas à porta WSDL.
if (context.WsdlPort != null)
{
AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);
}
A UdpTransportBindingElement
implementação do método também exporta ExportEndpoint
um URI de transporte quando o ponto de extremidade usa uma associação SOAP.
WsdlNS.SoapBinding soapBinding = GetSoapBinding(context, exporter);
if (soapBinding != null)
{
soapBinding.Transport = UdpPolicyStrings.UdpNamespace;
}
Importação WSDL
Para estender o sistema de importação WSDL para lidar com a importação dos endereços, devemos adicionar a seguinte configuração ao arquivo de configuração para Svcutil.exe conforme mostrado no arquivo Svcutil.exe.config.
<configuration>
<system.serviceModel>
<client>
<metadata>
<policyImporters>
<extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
Ao executar Svcutil.exe, há duas opções para obter Svcutil.exe para carregar as extensões de importação WSDL:
Aponte Svcutil.exe para o nosso arquivo de configuração usando o /SvcutilConfig:<file>.
Adicione a seção de configuração ao Svcutil.exe.config no mesmo diretório que Svcutil.exe.
O UdpBindingElementImporter
tipo implementa a IWsdlImportExtension
interface. O ImportEndpoint
método importa o endereço da porta WSDL.
BindingElementCollection bindingElements = context.Endpoint.Binding.CreateBindingElements();
TransportBindingElement transportBindingElement = bindingElements.Find<TransportBindingElement>();
if (transportBindingElement is UdpTransportBindingElement)
{
ImportAddress(context);
}
Adicionando suporte a políticas
O elemento de vinculação personalizado pode exportar asserções de política na associação WSDL para um ponto de extremidade de serviço para expressar os recursos desse elemento de vinculação.
Exportação de políticas
O UdpTransportBindingElement
tipo implementa IPolicyExportExtension
para adicionar suporte para exportar política. Como resultado, System.ServiceModel.MetadataExporter
inclui UdpTransportBindingElement
na geração de política para qualquer vinculação que a inclua.
No IPolicyExportExtension.ExportPolicy
, adicionamos uma asserção para UDP e outra asserção se estivermos no modo multicast. Isso ocorre porque o modo de multicast afeta como a pilha de comunicação é construída e, portanto, deve ser coordenada entre ambos os lados.
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));
}
Como os elementos de vinculação de transporte personalizados são responsáveis por lidar com o endereçamento, a IPolicyExportExtension
implementação no deve também lidar com a UdpTransportBindingElement
exportação das asserções de política WS-Addressing apropriadas para indicar a versão do WS-Addressing que está sendo usada.
AddWSAddressingAssertion(context, encodingBindingElement.MessageVersion.Addressing);
Importação de políticas
Para estender o sistema de importação de política, devemos adicionar a seguinte configuração ao arquivo de configuração para Svcutil.exe conforme mostrado no arquivo Svcutil.exe.config.
<configuration>
<system.serviceModel>
<client>
<metadata>
<policyImporters>
<extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
Em seguida, implementamos IPolicyImporterExtension
a partir de nossa classe registrada (UdpBindingElementImporter
). No ImportPolicy()
, examinamos as asserções em nosso namespace e processamos as que geram o transporte e verificamos se ele é multicast. Também devemos remover as asserções que lidamos da lista de asserções vinculativas. Novamente, ao executar Svcutil.exe, há duas opções de integração:
Aponte Svcutil.exe para o nosso arquivo de configuração usando o /SvcutilConfig:<file>.
Adicione a seção de configuração ao Svcutil.exe.config no mesmo diretório que Svcutil.exe.
Adicionando uma vinculação padrão
Nosso elemento de ligação pode ser usado das duas maneiras a seguir:
Através de uma associação personalizada: uma associação personalizada permite que o usuário crie sua própria associação com base em um conjunto arbitrário de elementos de ligação.
Usando uma ligação fornecida pelo sistema que inclui nosso elemento de ligação. O WCF fornece várias dessas ligações definidas pelo sistema, como
BasicHttpBinding
,NetTcpBinding
eWsHttpBinding
. Cada uma dessas ligações está associada a um perfil bem definido.
O exemplo implementa a vinculação de perfil em SampleProfileUdpBinding
, que deriva de Binding. O SampleProfileUdpBinding
contém até quatro elementos de ligação dentro dele: UdpTransportBindingElement
, TextMessageEncodingBindingElement CompositeDuplexBindingElement
, e 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();
}
Adicionando um importador de vinculação padrão personalizado
Svcutil.exe e o WsdlImporter
tipo, por padrão, reconhece e importa ligações definidas pelo sistema. Caso contrário, a associação será importada como uma CustomBinding
instância. Para permitir Svcutil.exe e importar WsdlImporter
o SampleProfileUdpBinding
UdpBindingElementImporter
também atua como um importador de vinculação padrão personalizado.
Um importador de vinculação padrão personalizado implementa o ImportEndpoint
método na IWsdlImportExtension
interface para examinar a CustomBinding
instância importada de metadados para ver se ela poderia ter sido gerada por uma associação padrão específica.
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;
}
}
}
Geralmente, a implementação de um importador de vinculação padrão personalizado envolve a verificação das propriedades dos elementos de vinculação importados para verificar se apenas as propriedades que poderiam ter sido definidas pela associação padrão foram alteradas e todas as outras propriedades são seus padrões. Uma estratégia básica para implementar um importador de vinculação padrão é criar uma instância da associação padrão, propagar as propriedades dos elementos de vinculação para a instância de vinculação padrão que a vinculação padrão suporta e comparar os elementos de ligação da associação padrão com os elementos de vinculação importados.
Adicionando suporte à configuração
Para expor nosso transporte através da configuração, devemos implementar duas seções de configuração. O primeiro é um BindingElementExtensionElement
para UdpTransportBindingElement
. Isso é para que CustomBinding
as implementações possam fazer referência ao nosso elemento de vinculação. O segundo é um para o Configuration
nosso SampleProfileUdpBinding
.
Elemento de extensão de elemento de ligação
A seção UdpTransportElement
é uma BindingElementExtensionElement
que expõe UdpTransportBindingElement
ao sistema de configuração. Com algumas substituições básicas, definimos nosso nome de seção de configuração, o tipo de nosso elemento de vinculação e como criar nosso elemento de ligação. Podemos então registrar nossa seção de extensão em um arquivo de configuração, conforme mostrado no código a seguir.
<configuration>
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="udpTransport" type="Microsoft.ServiceModel.Samples.UdpTransportElement, UdpTransport" />
</bindingElementExtensions>
</extensions>
</system.serviceModel>
</configuration>
A extensão pode ser referenciada a partir de ligações personalizadas para usar UDP como transporte.
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding configurationName="UdpCustomBinding">
<udpTransport/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
Secção Vinculativa
A seção SampleProfileUdpBindingCollectionElement
é uma StandardBindingCollectionElement
que expõe SampleProfileUdpBinding
ao sistema de configuração. A maior parte da implementação é delegada ao , que deriva SampleProfileUdpBindingConfigurationElement
de StandardBindingElement
. O SampleProfileUdpBindingConfigurationElement
tem propriedades que correspondem às propriedades em SampleProfileUdpBinding
e funções a serem mapeadas a ConfigurationElement
partir da associação. Finalmente, substitua o OnApplyConfiguration
método em nosso SampleProfileUdpBinding
, conforme mostrado no código de exemplo a seguir.
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;
}
Para registrar esse manipulador no sistema de configuração, adicionamos a seção a seguir ao arquivo de configuração relevante.
<configuration>
<configSections>
<sectionGroup name="system.serviceModel">
<sectionGroup name="bindings">
<section name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />
</sectionGroup>
</sectionGroup>
</configSections>
</configuration>
Em seguida, ele pode ser referenciado na seção de configuração 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>
O Serviço de Teste UDP e o Cliente
O código de teste para usar esse transporte de exemplo está disponível nos diretórios UdpTestService e UdpTestClient. O código de serviço consiste em dois testes — um teste configura ligações e pontos de extremidade do código e o outro faz isso por meio da configuração. Ambos os testes usam dois parâmetros. Um ponto de extremidade usa o SampleUdpProfileBinding
conjunto com< reliableSession> como true
. O outro ponto de extremidade usa uma associação personalizada com UdpTransportBindingElement
. Isso é equivalente a usar SampleUdpProfileBinding
com <reliableSession> definido como false
. Ambos os testes criam um serviço, adicionam um ponto de extremidade para cada ligação, abrem o serviço e aguardam que o usuário pressione ENTER antes de fechar o serviço.
Ao iniciar o aplicativo de teste de serviço, você verá a saída a seguir.
Testing Udp From Code.
Service is started from code...
Press <ENTER> to terminate the service and start service from config...
Em seguida, você pode executar o aplicativo cliente de teste nos pontos de extremidade publicados. O aplicativo de teste cliente cria um cliente para cada ponto de extremidade e envia cinco mensagens para cada ponto de extremidade. A saída a seguir está no cliente.
Testing Udp From Imported Files Generated By SvcUtil.
0
3
6
9
12
Press <ENTER> to complete test.
A seguir está a saída completa no serviço.
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
Para executar o aplicativo cliente em pontos de extremidade publicados usando a configuração, pressione ENTER no serviço e execute o cliente de teste novamente. Você deve ver a seguinte saída no serviço.
Testing Udp From Config.
Service is started from config...
Press <ENTER> to terminate the service and exit...
Executar o cliente novamente produz o mesmo que os resultados anteriores.
Para regenerar o código do cliente e a configuração usando Svcutil.exe, inicie o aplicativo de serviço e execute o seguinte Svcutil.exe a partir do diretório raiz do exemplo.
svcutil http://localhost:8000/udpsample/ /reference:UdpTransport\bin\UdpTransport.dll /svcutilConfig:svcutil.exe.config
Observe que Svcutil.exe não gera a configuração de extensão de vinculação para o SampleProfileUdpBinding
, portanto, você deve adicioná-lo manualmente.
<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>
Para configurar, compilar e executar o exemplo
Para criar a solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.
Para executar o exemplo em uma configuração de máquina única ou cruzada, siga as instruções em Executando os exemplos do Windows Communication Foundation.
Consulte a seção anterior "O serviço de teste UDP e o cliente".