Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A primeira etapa na escrita de 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 canal descrita em Canais de Desenvolvimento.
Seis padrões de troca de mensagens
Há três deputados para escolher:
Datagrama (IInputChannel e IOutputChannel)
Ao usar um MEP de datagrama, um cliente envia uma mensagem usando uma troca disparar e esquecer. Uma troca do tipo disparar e esquecer é aquela que requer confirmação de entrega bem-sucedida fora da faixa. 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 lado do cliente, isso não garante que o ponto de extremidade remoto tenha recebido a mensagem. O datagram é um bloco de construção fundamental para mensagens, pois você pode criar seus próprios protocolos em cima dele, incluindo protocolos confiáveis e protocolos seguros. Os canais de datagrama do cliente implementam a interface IOutputChannel e os canais de datagrama de serviço implementam a interface IInputChannel.
Solicitação-resposta (IRequestChannel e IReplyChannel)
Nesse MEP, uma mensagem é enviada e uma resposta é recebida. 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. Esse padrão também é conhecido como half-duplex. Neste MEP, os canais de cliente implementam IRequestChannel e os canais de serviço implementam IReplyChannel.
Duplex (IDuplexChannel)
O MEP duplex permite que um número arbitrário de mensagens seja enviado por um cliente e recebido em qualquer ordem. O MEP duplex é como uma conversa telefônica, onde cada palavra que está sendo falada é uma mensagem. Como ambos os lados podem enviar e receber neste MEP, a interface implementada pelo cliente e pelos canais de serviço é IDuplexChannel.
Os três padrões básicos de troca de mensagens. De cima para baixo: datagrama, solicitação-resposta e duplex.
Cada um desses MEPs também pode dar suporte a sessões. Uma sessão (e a implementação de System.ServiceModel.Channels.ISessionChannel<TSession> do tipo System.ServiceModel.Channels.ISession) correlaciona todas as mensagens enviadas e recebidas em um canal. O padrão de solicitação-resposta é uma sessão autônoma de duas mensagens, pois a solicitação e a resposta são correlacionadas. Por outro lado, o padrão solicitação-resposta que dá suporte a 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 para escolher:
Datagrama
Solicitação-resposta
Duplex
Datagrama com sessões
Solicitação-resposta com sessões
Duplex com sessões
Observação
Para o transporte UDP, o único MEP com suporte é o datagrama, pois o UDP é inerentemente um protocolo do tipo disparar e esquecer.
Sessões e canais com sessão
No mundo da rede, há protocolos orientados para conexão (por exemplo, TCP) e protocolos sem conexão (por exemplo, UDP). O WCF usa o termo sessão para referir-se a uma abstração lógica similar a uma conexão. Os protocolos WCF com sessão são semelhantes aos protocolos de rede orientados à 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 com sessão. Portanto, cada nova sessão criada pelo cliente e aceita no serviço corresponde a um novo canal de sessão em cada lado. O diagrama a seguir mostra, na parte superior, a estrutura de canais sem sessão e, na parte inferior, a estrutura de canais com sessão.
Um cliente cria um novo canal com sessão e envia uma mensagem. No lado do serviço, o ouvinte de canais recebe essa mensagem e detecta que ela pertence a uma nova sessão, então ele cria um canal de sessão e o entrega ao aplicativo (em resposta ao aplicativo que chama AcceptChannel no ouvinte do canal). Em seguida, o aplicativo recebe essa mensagem e todas as mensagens subsequentes enviadas na mesma sessão por meio 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 detecta que essa mensagem está em uma nova sessão e cria um canal com 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 por meio do qual todas as mensagens recebidas são entregues ao aplicativo. Também não há nenhuma ordenação de mensagens porque não há nenhuma sessão na qual manter a ordem da mensagem. 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 com sessão. Elas são iniciadas 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 anulando um canal com sessão.
A exceção a isso é IDuplexSessionChannel, que é usado para enviar e receber mensagens em um padrão de comunicação duplex e com sessão. É possível que um lado queira parar de enviar mensagens, mas continuar recebendo 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 recebendo mensagens.
Em geral, as sessões são fechadas no lado de saída e não no lado de entrada. Ou seja, os canais de saída com sessão podem ser fechados, encerrando a sessão corretamente. O fechamento de um canal de saída com sessão faz com que o canal de entrada com sessão correspondente retorne nulo para o aplicativo que está chamando IInputChannel.Receive no IDuplexSessionChannel.
No entanto, os canais de entrada com sessão não devem ser fechados, a menos que IInputChannel.Receive no IDuplexSessionChannel retorne nulo, indicando que a sessão já está fechada. Se IInputChannel.Receive no IDuplexSessionChannel não tiver retornado nulo, fechar um canal de entrada com sessão poderá gerar uma exceção, porque ele poderá receber mensagens inesperadas durante o fechamento. Se um receptor quiser encerrar uma sessão antes do remetente, ele deverá chamar Abort no canal de entrada, o que encerra abruptamente a sessão.
Escrevendo canais com sessão
Como autor de canal com sessão, há algumas coisas que seu canal deve fazer para fornecer sessões. No lado do envio, o 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 este canal, se o canal criou a sessão (em vez de obtê-la da camada abaixo de você), você precisará associar a mensagem à sessão. Para canais de protocolo, isso normalmente é feito adicionando um cabeçalho SOAP. Para canais de transporte, isso normalmente é feito criando uma nova conexão de transporte ou adicionando informações de sessão ao protocolo de enquadramento.
Para cada mensagem enviada usando este canal, você precisa fornecer as garantias de entrega mencionadas acima. Se você estiver contando com o canal abaixo 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 protocolo. Em geral, se você estiver escrevendo um canal de protocolo que pressupõe WCF em ambos os lados, poderá exigir o transporte TCP ou o canal de Mensagens Confiáveis e contar com 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 chamar Close no canal abaixo de você (se você acabou de obter a sessão dela) ou enviar uma mensagem SOAP especial ou fechar uma conexão de transporte.
Quando Abort for chamado em seu canal, encerre a sessão abruptamente sem executar E/S. Isso pode significar não fazer nada ou pode envolver a anulação de uma conexão de rede ou algum outro recurso.
No lado de recebimento, seu canal precisa:
Para cada mensagem de entrada, o ouvinte de canal deve detectar a sessão à qual pertence. Se essa for a primeira mensagem na sessão, o ouvinte do canal deverá criar um novo canal e retorná-lo da chamada para IChannelListener<TChannel>.AcceptChannel. Caso contrário, o ouvinte de canal deverá encontrar o canal existente que corresponde à sessão e entregar a mensagem por meio desse canal.
Se o canal estiver fornecendo a sessão (juntamente com as garantias de entrega necessárias), o lado de recebimento poderá precisar 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 usando o tempo limite especificado ou o padrão. Isso poderá resultar em exceções se o canal receber uma mensagem enquanto aguarda o tempo limite de fechamento expirar. Isso ocorre porque o canal estará no estado Fechando quando receber uma mensagem para que ele seja lançado.
Quando Abort for chamado em seu canal, encerre a sessão abruptamente sem executar E/S. Novamente, isso pode significar não fazer nada ou pode envolver a anulação de uma conexão de rede ou algum outro recurso.