Partilhar via


Escolhendo um padrão de troca de mensagens

O primeiro passo para escrever um transporte personalizado é decidir quais padrões de troca de mensagens (ou MEPs) são necessários para o canal que você está desenvolvendo. Este tópico descreve as opções disponíveis e discute os vários requisitos. Esta é a primeira tarefa na lista de tarefas de desenvolvimento de canais descrita em Canais em desenvolvimento.

Seis padrões de troca de mensagens

Há três deputados ao Parlamento Europeu à escolha:

  • Datagrama (IInputChannel e IOutputChannel)

    Ao usar um datagrama MEP, um cliente envia uma mensagem usando uma troca de fogo e esquecimento . 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.

  • Pedido-Resposta (IRequestChannel e 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 solicitações GET 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.

Flowchart showing the three basic message exchange patterns
Os três padrões básicos de troca de mensagens. De cima para baixo: datagrama, solicitação-resposta e duplex.

Cada um destes deputados também pode apoiar as sessões. Uma sessão (e implementação do System.ServiceModel.Channels.ISessionChannel<TSession> tipo System.ServiceModel.Channels.ISession) correlaciona todas as mensagens enviadas e recebidas em um canal. O padrão solicitação-resposta é uma sessão autônoma de duas mensagens, pois a solicitação e a resposta estão correlacionadas. Em contraste, o padrão solicitação-resposta que suporta sessões implica que todos os pares solicitação/resposta nesse canal estão correlacionados entre si. Isto dá-lhe um total de seis deputados ao Parlamento Europeu à sua escolha:

  • Diagrama

  • Solicitação-resposta

  • Duplex

  • Datagrama com sessões

  • Solicitação-resposta com sessões

  • Duplex com sessões

Nota

Para o transporte UDP, o único MEP suportado é o datagrama, porque o UDP é inerentemente um protocolo de incêndio e esquecimento.

Sessões e Canais de Sessões

No mundo da rede, existem protocolos orientados para conexão (por exemplo, TCP) e protocolos sem conexão (por exemplo, UDP). WCF usa o termo sessão para significar uma abstração lógica semelhante a uma conexão. Os protocolos WCF com sessão são semelhantes aos protocolos de rede orientados a conexão e os protocolos WCF sem sessão são semelhantes aos protocolos de rede sem conexão.

No modelo de objeto de canal, cada sessão lógica se manifesta como uma instância de um canal de sessão. Portanto, cada nova sessão criada pelo cliente, e aceita no serviço, corresponde a um novo canal de sessão de cada lado. O diagrama a seguir mostra, na parte superior, a estrutura dos canais sem sessão e, na parte inferior, a estrutura dos canais sem sessão.

Flowchart showing the structure of sessionless and sessionful channels

Um cliente cria um novo canal de sessão e envia uma mensagem. No lado do serviço, o ouvinte do canal recebe essa mensagem e deteta que ela pertence a uma nova sessão, criando um novo canal de sessão e entregando-a ao aplicativo (em resposta ao aplicativo chamando AcceptChannel no ouvinte do canal). Em seguida, o aplicativo recebe essa mensagem e todas as mensagens subsequentes enviadas na mesma sessão através do mesmo canal de sessão.

Outro cliente (ou o mesmo cliente) cria uma nova sessão e envia uma mensagem. O ouvinte do canal deteta que essa mensagem está em uma nova sessão e cria um novo canal de sessão e o processo se repete.

Sem sessões, não há correlação entre canais e sessões. Portanto, um ouvinte de canal cria apenas um canal através do qual todas as mensagens recebidas são entregues ao aplicativo. Também não há ordenação de mensagens porque não há nenhuma sessão dentro da qual manter a ordem das mensagens. A parte superior do gráfico anterior ilustra uma troca de mensagens sem sessão.

Iniciando e encerrando sessões

As sessões são iniciadas no cliente simplesmente criando um novo canal de sessão. Eles são iniciados no serviço quando o serviço recebe uma mensagem que foi enviada em uma nova sessão. Da mesma forma, as sessões são encerradas fechando ou abortando um canal de sessão.

A exceção é IDuplexSessionChannel que é usada para enviar e receber mensagens em um padrão de comunicação duplex e com sessão. É possível que um dos lados queira parar de enviar mensagens, mas continuar a receber mensagens, portanto, ao usar IDuplexSessionChannel , há um mecanismo que permite fechar a sessão de saída, indicando que você não enviará mais mensagens, mas manterá a sessão de entrada aberta, permitindo que você continue a receber mensagens.

Em geral, as sessões são encerradas no lado de saída e não no lado de entrada. Ou seja, os canais de saída de sessão podem ser fechados, encerrando assim a sessão de forma limpa. Fechar um canal de saída sessionful faz com que o canal de entrada sessionful correspondente retorne null para o aplicativo que chama IInputChannel.Receive o IDuplexSessionChannel.

No entanto, os canais de entrada de sessão não devem ser fechados, a menos IInputChannel.Receive que nos retornos IDuplexSessionChannel null, indicando que a sessão já está fechada. Se IInputChannel.Receive no não tiver retornado nulo, fechar um canal de entrada com sessão pode gerar uma exceção porque ele pode receber mensagens inesperadas durante o IDuplexSessionChannel fechamento. Se um recetor deseja encerrar uma sessão antes que o remetente o faça, ele deve chamar Abort o canal de entrada, que encerra abruptamente a sessão.

Escrevendo canais de sessão

Como autor de um canal com sessão, há algumas coisas que seu canal deve fazer para fornecer sessões. No lado do envio, seu canal precisa:

  • Para cada novo canal, crie uma nova sessão e associe-a a uma nova ID de sessão, que é uma cadeia de caracteres exclusiva. Ou obtenha uma nova sessão do canal de sessão abaixo de você na pilha.

  • Para cada mensagem enviada usando esse canal, se o seu canal criou a sessão (em vez de obtê-la da camada abaixo de você), você precisa associar a mensagem à sessão. Para canais de protocolo, isso geralmente é feito adicionando um cabeçalho SOAP. Para canais de transporte, isso geralmente é feito criando uma nova conexão de transporte ou adicionando informações de sessão ao protocolo de enquadramento.

  • Para cada mensagem enviada através deste canal, você precisa fornecer as garantias de entrega mencionadas acima. Se você estiver confiando no canal abaixo de você para fornecer a sessão, esse canal também fornecerá as garantias de entrega. Se você estiver fornecendo a sessão por conta própria, precisará implementar essas garantias como parte do seu protocolo. Em geral, se você estiver escrevendo um canal de protocolo que assume WCF em ambos os lados, você pode exigir o transporte TCP ou o canal de mensagens confiáveis e confiar em qualquer um deles para fornecer uma sessão.

  • Quando ICommunicationObject.Close for chamado em seu canal, execute o trabalho necessário para fechar a sessão usando o tempo limite especificado ou o padrão. Isso pode ser tão simples quanto ligar Close para o canal abaixo de você (se você acabou de obter a sessão dele) ou enviar uma mensagem SOAP especial ou fechar uma conexão de transporte.

  • Quando Abort for chamado no seu canal, encerre a sessão abruptamente sem executar E/S. Isso pode significar não fazer nada ou pode envolver o cancelamento de uma conexão de rede ou algum outro recurso.

No lado da receção, seu canal precisa:

  • Para cada mensagem recebida, o ouvinte do canal deve detetar a sessão à qual pertence. Se esta for a primeira mensagem na sessão, o ouvinte do canal deve criar um novo canal e devolvê-lo da chamada para IChannelListener<TChannel>.AcceptChannel. Caso contrário, o ouvinte do canal deve encontrar o canal existente que corresponde à sessão e entregar a mensagem através desse canal.

  • Se o seu canal estiver fornecendo a sessão (juntamente com as garantias de entrega necessárias), o lado do recebimento pode ser solicitado a executar algumas ações, como reordenar mensagens ou enviar confirmações.

  • Quando Close for chamado em seu canal, execute o trabalho necessário para fechar a sessão no tempo limite especificado ou no padrão. Isso pode resultar em exceções se o canal receber uma mensagem enquanto aguarda o tempo limite de fechamento expirar. Isso porque o canal estará no estado de Fechamento quando receber uma mensagem para que seja lançada.

  • Quando Abort for chamado no seu canal, encerre a sessão abruptamente sem executar E/S. Novamente, isso pode significar não fazer nada ou pode envolver abortar uma conexão de rede ou algum outro recurso.

Consulte também