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