Message broadcast with multiple receivers - c#

I have a mainform that sends messages and a random number of receive forms that run as separate application (C# 4.0).
Everytime one of the random number of forms receive's the message but than the message is received and the others won't receive it anymore.
I've tried this with UDP, TCP IP, MSMQ but I don't seem to get it working well. The sender and receivers run on the same system.
Can anyone recommend me a way to broadcast a message that stays in a sort of queue till all the forms have received it, or maybe it can stay in that queue till the application closes, but how...?
Thanks in advance people!
Kind regards
Wesley

Multicast MSMQ
You can use MSMQ with Multicast option (check that your Windows installation has that option before trying it, you will find it in the "add/remove windows features" section of the Windows control panel).
A sender using the MSMQ Multicast Queue will submit a message that can be processed by many MSMQ Multicast Queue receivers.
Receiver
The reader must have a private queue, then you will need to set the multicast address that you want to use (the choice of the multicast address is arbitrary, that's why you will often see the same address mentionned in different posts, see the msdn docs for more information), like this:
var myQueue = MessageQueue.Create(".\private$\MulticastTest", false);
myQueue.MulticastAddress = "234.1.1.1:8001";
or directly use the existing multicast queue (if it has been created with the multicast address) the standard way:
var myQueue = new MessageQueue(multicastQueueName());
Then you will have to listen for new messages using your prefered method, I prefer to use this one:
myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
myQueue.PeekCompleted += new PeekCompletedEventHandler(QueuePeekCompleted);
myQueue.BeginPeek();
The delegate QueuePeekCompleted looks like this:
private void QueuePeekCompleted(object sender, PeekCompletedEventArgs e)
{
try
{
var message = myQueue.EndPeek(e.AsyncResult);
//LogInfo("Received this : " + message.Body);
}
catch (Exception ex)
{
//LogError(ex);
}
myQueue.Receive();
myQueue.BeginPeek();
}
Sender
The sender of a multicast message must connect to the multicast queue like this:
MessageQueue myQueue = new MessageQueue("formatname:multicast=234.1.1.1:8001");
Then send a message as usual:
myQueue.Send("hey listen!");

The messaging pattern you are looking for is called publish-subscribe. MSMQ does not support this messaging pattern natively.
However there are a number of open source tools which do including RabbitMQ and NServiceBus.

Related

C# - I want to listen to a group in Telegram from more than one program

I can listen to a group through a program, but I want to listen to the same group with more than one program at the same time.
thanks in advance
static ITelegramBotClient botClient = new TelegramBotClient("123456789:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
botClient.OnMessage += Bot_OnMesaage;
botClient.StartReceiving();
public void Bot_OnMesaage(object sender, Telegram.Bot.Args.MessageEventArgs e)
{
if (e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Text)
{
Debug(e.Message.Text);
}
}
According to a Telegram.Bot FAQ (409 error section) you can't duplicate the messages that you get by long-polling (and I assume that in your case you're long-polling telegram for getting updates) so you can't make multiple instances of your bot like that.
The possible way is to create a webhook provided either by your own internet server that will process messages from telegram or by something like ngrok tunnel to multiple instances.

How do you loop in C# until a new email has arrived?

using System;
using Limilabs.Mail;
using Limilabs.Client.POP3;
class Program
{
static void Main(string[] args)
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Users\*******\Desktop\WriteLines.txt", true)){
using (Pop3 pop3 = new Pop3())
{
Console.WriteLine("Connecting...");
pop3.ConnectSSL("pop3.live.com"); // or ConnectSSL for SSL
pop3.Login("****#live.com", "****");
// Receive all messages and display the subject
MailBuilder builder = new MailBuilder();
foreach (string uid in pop3.GetAll())
{
IMail email = builder.CreateFromEml(
pop3.GetMessageByUID(uid));
file.WriteLine("Header: " + email.Subject);
file.WriteLine("Message: " + email.Text);
}
pop3.Close();
}
}
}
}
So I have this problem where I want to have this program running 24/7; it is still incomplete but this is just to show basic C# retrieving emails and such. How can I have a loop in C# that only gets halted or forced to anything only when a new email arrives in the inbox? I would like the program only to actually do something upon getting an email sent to in in realtime. I know I can go and print out my emails one by one all at once but I want it to be running and only when a new message is received do I want i to do anything. For example idk, if I was to send a message like clean desktop, it would stop and be parsed and if a valid command sequence specified by another program I am going to make, then it will carry out that command and then keep on looping endlessly waiting for another new message. It'll basically be a server running 24/7 that only responds to new emails. That is what I am going for. All help is greatly appreciated.
Pop3 is a polling protocol. It does not allow to inform you that a new mail has arrived. You would have to e.g. the Exchange protocol that supports this afaik. Thus, for POP3 mailboxes, mail programs usually poll for new emails every e.g. 15min. I'd suspect that your POP3-library does not support this directly. Thus, you would have to use a Timer class and poll for new emails.
Documentation for the Timer class can be found in the MSDN library:
http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx
You would probably want to use a windows service that polls your email inbox.
A similar question was asked about how to do this here. One of the answers provides a good layout in how to do this.
In addition, if you are trying have your website perform this functionality (because you don't have access to install a windows service) you could use Quartz.net highlighted in this question.

C# MQ Api How to fetch message without getting exception in case of empty queue

I have to periodically check messages in a queue within Websphere MQ. I haven't found better approach rather than try getting a message and handle 2033 reason code (which is NO_MSG_AVAILABLE) like this:
try
{
// ...
inQueue.Get(message);
}
catch (MQException exception)
{
if (exception.ReasonCode != 2033)
throw;
}
Is there better way to get message from queue? I think that there might be some openOptions flag that I'm not aware of, that wouldn't throw exception when no message available, but return null instead.
There are three ways to avoid or reduce this polling mechanism.
Here they are in oder of elegance(the higher the better):
MQGET with wait interval UNLIMITED and MQGMO_FAIL_IF_QUIESCING
Get your application be triggered by MQServer
Callback function - new with MQ V7 on both sides
You are missing the MQC.MQGMO_WAIT flag on MQGetMessageOptions.Options. Change it this way:
getOptions = new MQGetMessageOptions {WaitInterval = MQC.MQWI_UNLIMITED, Options = MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING}
Please note that this would make the calling thread to be blocked till a message arrives at the queue or some connection exception occurs. MQ has another client called IBM Message Service Client (aka XMS .NET) that provides a JMS specification implementation in .NET. This has a nice little Message Listener which gets automatically invoked whenever a message arrives in a queue. Unlike in the above example, the calling thread will not be blocked when Message Listener is used.
More details on XMS .NET can be found here. Samples are also shipped with MQ and for message listener sample, please refer "SampleAsyncConsumer.cs" source file.
I was getting this. I solved it by putting the Message initiator inside the loop:
_queueManager = new MQQueueManager(Queuemanager, _mqProperties);
MQQueue queue = _queueManager.AccessQueue(
Queuename,
MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_INQUIRE);
string xml = "";
while (queue.CurrentDepth > 0)
{
MQMessage message = new MQMessage();
queue.Get(message);
xml = message.ReadString(message.MessageLength);
MsgQueue.Enqueue(xml);
message.ClearMessage();
}
There must be something in the Message internally that errors when reusing it for another get.

How do you configure multiple message consumers in MassTransit?

I'm looking at using MassTransit to publish a event from one process to all other processes that care about that event. In my environment, several processes that are subscribed to that event could be running on the same box.
Based on the MassTransit's example code, here's a VERY simple proof-of-concept that does not attempt to deal with multi-cast (processes will also be distributed across many machines). Consider the "Message" below as an "Event", and that I want every instance of this process to get that message:
using System;
using MassTransit;
namespace BasicPubSub
{
public class Message
{
public String Text { get; set; }
}
public class Program
{
static void Main(string[] args)
{
//initialize the bus
var bus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
//cause the DTC and MSMQ to get installed/fixed if needed.
sbc.VerifyMsDtcConfiguration();
sbc.VerifyMsmqConfiguration();
//sbc.UseMulticastSubscriptionClient();//Doesn't behave for a private queue.
sbc.ReceiveFrom("msmq://localhost/test_queue");
//Listen for interesting events.
sbc.Subscribe(subs =>
{
subs.Handler<Message>(msg => Console.WriteLine(msg.Text));
});
});
//stay open until the user types "exit"
var message = "";
do
{
message = Console.ReadLine();
//broadcast the message
bus.Publish(new Message { Text = message });
} while (message != "exit");
}
}
}
If I run multiple instances of this C# app, only one of the instances receives the message, but I need all of the instances to receive it. This behavior is consistent with the classical notion of a queue, so I'm fine with that.
What I am looking to know is whether I can use MSMQ/MassTransit to publish a message that all subscribers will receive, as opposed to just a single subscriber dequeuing it and the others not receiving it. Perhaps I'm trying to use a hammer and I need a paintbrush?
Just to be clear here, I am not looking at sharing a single queue for different kinds of messages, I'm looking to setup "peer-to-peer" pub-sub for a specific type of message, using MT and MSMQ.
I'm not sure about hammers or paintbrushes, but I think you're heading in the right direction.
To start with, each instance of a bus requires it's own queue to read from. If you are running multiple versions of this same program, make sure they are reading off different queues. Attempting to read from the same queue leads to Bad Stuff(TM).
Join the mailing list if you have more questions. https://groups.google.com/forum/#!forum/masstransit-discuss.
When publishing, all consumers should recieve the message once they have been subscribed. It might take a second or two for the subscription data to pass to all processes when starting up.
I would also suggest taking a look at RabbitMQ. Unless you absolutely need DTC, RabbitMQ is a much more robust messaging platform.

clear Message Queue in C#

I use the Message Queue to send messages from one application to the other one (this has to work only on one particular machine)
I create the queue like this on the receiver side:
string queueName = ".\\private$\\WZMSGQ";
if (MessageQueue.Exists(queueName))
msgQueue = new MessageQueue(queueName);
else
msgQueue = MessageQueue.Create(queueName, false);
and after this I start the sender application, where I create the queue like that:
msgQueue = new MessageQueue(".\\private$\\WZMSGQ");
in the receiver Application I then retrieve new messages:
Message[] messages = msgQueue.GetAllMessages();
foreach (Message msg in messages){
doSomething();
}
Now I'd like to do two things:
I would like to clear the message queue when instantiating the new MessageQueue instance on the receiver machine such that all old messages are gone.
I'd like to delete the message queue when the program ends, such that it does not exist anymore if I start the application the next time
How can I do that?
MessageQueue.Purge and MessageQueue.Delete seem to be what you want, unless I have misread the question.

Categories