Agora é a vez de invertemos a situação em relação ao post anterior. Vamos criar um cliente síncrono e um servidor assíncrono.
Vamos lá, crie um projeto C# do tipo console, versão 4.5 do .NET com o nome zeromq.testes.sync-request. Instale o ZeroMQ via NuGet com install-package clrzmq -pre.
Vamos fazer o mesmo para o nosso servidor assíncrono. Crie um projeto com as mesmas características e dê o nome de zeromq.testes.async-reply. Instale o ZeroMQ como no projeto anterior.
Use o trecho de código a seguir para o cliente -- request.
Use o trecho de código a seguir para o servidor -- reply.
Vamos lá, crie um projeto C# do tipo console, versão 4.5 do .NET com o nome zeromq.testes.sync-request. Instale o ZeroMQ via NuGet com install-package clrzmq -pre.
Vamos fazer o mesmo para o nosso servidor assíncrono. Crie um projeto com as mesmas características e dê o nome de zeromq.testes.async-reply. Instale o ZeroMQ como no projeto anterior.
Código
Use o trecho de código a seguir para o cliente -- request.
using System; using System.Collections.Generic; using System.Text; using System.Threading; using ZeroMQ; namespace zeromq.testes.sync_request { class Program { static void Main(string[] args) { using (var context = ZmqContext.Create()) using (var socket = context.CreateSocket(SocketType.REQ)) { socket.Connect("tcp://127.0.0.1:5555"); while (true) { string request_body = Guid.NewGuid().ToString(); ZmqMessage request = new ZmqMessage(new List<byte[]> { Encoding.Unicode.GetBytes(request_body), }); socket.SendMessage(request); Console.WriteLine("{0} - requisição enviada: {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), request_body); ZmqMessage resposta = socket.ReceiveMessage(); Console.WriteLine("{0} - resposta recebida: {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Encoding.Unicode.GetString(resposta[0])); Thread.Sleep(2000); } } } } }
Use o trecho de código a seguir para o servidor -- reply.
using System; using System.Collections.Generic; using System.Text; using ZeroMQ; namespace zeromq.testes.async_reply { class Program { static void Main(string[] args) { using (ZmqContext context = ZmqContext.Create()) using (ZmqSocket router = context.CreateSocket(SocketType.ROUTER)) { router.Bind("tcp://*:5555"); router.ReceiveReady += (sender, eventArgs) => { ZmqMessage request_msg = eventArgs.Socket.ReceiveMessage(); string request_body = Encoding.Unicode.GetString(request_msg[2].Buffer); string reply_body = request_body.Replace("-", string.Empty).ToUpper(); Console.WriteLine("{0} - resposta enviada: {1}", DateTime.Now, reply_body); ZmqMessage reply_msg = new ZmqMessage(new List<byte[]> { request_msg[0].Buffer, // Id da requisição Encoding.Unicode.GetBytes(string.Empty), // truque necessário Encoding.Unicode.GetBytes(reply_body), // conteúdo da resposta }); router.SendMessage(reply_msg); }; Poller poller = new Poller(new List<ZmqSocket> { router }); while (true) { poller.Poll(); } } } } }
Execute os dois projetos ao mesmo tempo e você deverá ver o resultado: os dois consoles exibindo trocas de mensagens.
Truques
Assim como no exemplo anterior, aqui também há truques que se você souber de antemão, sua vida terá mais qualidade ;)
Linha 21 do server: A requisição síncrona é composta por basicamente 3 frames: 1) O Id do componente de requisição (também chamado de endereço) 2) Um frame vazio delimitador e 3) O corpo propriamente dito da mensagem. Dessa forma, nessa linha obtemos o corpo da mensagem.
Linha 27 do servidor (29, 30, e 31 na verdade): Como explicado acima, a requisição vem com um frame indicando o endereço, um delimitador nulo e o corpo da mensagem. Sendo assim, nós temos que devolver a mensagem de resposta da mesma forma. Caso contrário, o componente da requisição vai descartar a mensagem de resposta não a reconhecendo como uma mensagem válida. Acredite, foi um porre descobrir isso... Eu queria ter visto isso nos exemplos, mas acabei tendo que ler a documentação.
Linha 41 do servidor: Como o socket ROUTER é assíncrono, nós temos que usar o Poller para que o evento registrado na linha 17 seja disparado.
Uma outra questão que ainda não mencionei em nenhum outro post sobre o ZeroMQ: o tal do Bind e Connect. Por padrão, o lado "servidor" da relação, geralmente usa Bind, e o lado "cliente" usa Connect. O Bind só pode ser feito em um endereço e o Connect não tem restrição; mais de um Connect pode ser feito em um endereço.
Se você se interessou pelo ZeroMQ, dê uma boa lida em seu guia em http://zguide.zeromq.org/page:all. É longo, mas é um material muito bom e tem exemplos em muitas linguagens (inclusive C#) para a maioria dos padrões explicados.
Nenhum comentário:
Postar um comentário