I used the tutorial from rabbitMQ on RCP in C#
server program.cs
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
namespace RabbitMQServerTest
{
internal class Program
{
static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue:"RPC_TEST",true,false,false,null);
channel.BasicQos(0,1,false);
var consumer = new EventingBasicConsumer(channel);
channel.BasicConsume(queue: "RPC_TEST",
autoAck: true, consumer: consumer);
Console.WriteLine(" [x] Awaiting RPC requests");
consumer.Received += (model, ea) =>
{
string response = null;
var body = ea.Body.ToArray();
var props = ea.BasicProperties;
var replyProps = channel.CreateBasicProperties();
replyProps.CorrelationId = props.CorrelationId;
try
{
var message = Encoding.UTF8.GetString(body);
int n = int.Parse(message);
Console.WriteLine($" [.] fib({message}) from {replyProps.CorrelationId }");
response = fib(n).ToString();
}
catch (Exception e)
{
Console.WriteLine(" [.] " + e.Message);
response = "";
}
finally
{
var responseBytes = Encoding.UTF8.GetBytes(response);
channel.BasicPublish(exchange: "", routingKey: props.ReplyTo,
basicProperties: replyProps, body: responseBytes);
channel.BasicAck(deliveryTag: ea.DeliveryTag,
multiple: false);
}
};
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
}
private static int fib(int n)
{
if (n == 0 || n == 1)
{
return n;
}
return fib(n - 1) + fib(n - 2);
}
}
}
client program.cs
internal class Program
{
private static RpcClient m_rpcClient;
static void Main(string[] args)
{
m_rpcClient = new RpcClient();
callFib();
m_rpcClient.Close();
}
static void callFib()
{
Console.WriteLine("Write number:");
var num = Console.ReadLine();
if (num != "q")
{
var response = m_rpcClient.Call("30").Result;
Console.WriteLine(" [.] Got '{0}'", response);
callFib();
}
}
}
client RpcClient.cs
public class RpcClient :IDisposable
{
private readonly IConnection connection;
private readonly IModel channel;
private readonly string replyQueueName;
private readonly EventingBasicConsumer consumer;
private ConcurrentDictionary<string, TaskCompletionSource<string>> m_ActiveQueue = new ConcurrentDictionary<string, TaskCompletionSource<string>>();
private readonly IBasicProperties props;
public RpcClient()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
connection = factory.CreateConnection();
channel = connection.CreateModel();
replyQueueName = channel.QueueDeclare().QueueName;
consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var response = Encoding.UTF8.GetString(body);
if (m_ActiveQueue.TryRemove(ea.BasicProperties.CorrelationId, out
var taskCompletionSource))
{
taskCompletionSource.SetResult(response);
}
};
channel.BasicConsume(
consumer: consumer,
queue: replyQueueName,
autoAck: true);
}
public Task<string> Call(string message)
{
var props = channel.CreateBasicProperties();
var correlationId = Guid.NewGuid().ToString();
props.CorrelationId = correlationId;
props.ReplyTo = replyQueueName;
var taskCompletionSource = new TaskCompletionSource<string>();
var messageBytes = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(
exchange: "",
routingKey: "RPC_TEST",
basicProperties: props,
body: messageBytes);
m_ActiveQueue.TryAdd(correlationId, taskCompletionSource);
return taskCompletionSource.Task;
}
public void Close()
{
try
{
channel?.Close();
connection?.Close();
}
catch (Exception ex)
{
}
}
public void Dispose()
{
Close();
}
}
It's working only with single message from single client
if I'm trying to run few clients , only the first that sent the message get response
the seconds message sends the server doesn't even get to the consumer.Received event in server program.cs