Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Chat Using MSMQ

2.91/5 (14 votes)
17 Nov 2008CPOL5 min read 47K   1.6K  
Communation between two machines using MSMQ.

Introduction

This is a chatting application for use in a LAN using MSMQ. In this, we will have a server where we will maintain all the messages, and the client machine which can send or receive messages.

Installation

Before using this application, we should install MSMQ on the server and the client machine. MSMQ is a functionality provided by Microsoft Windows. While installing the Operating System, by default, it will not get installed; you have to install it manually from Control Panel->Add/Remove Programs->Add Remove Windows Components->Message Queuing.

What is MSMQ?

MSMQ is Microsoft’s Message Queuing, which allows communicating between two computers. Send and receive messages without worrying of their delivery to another machine. MSMQ allows putting messages in a queue, and if the user is not present, the messages will be in the queue. Once it is received by the user it will get deleted. In many applications, there is a need to send data or messages to another system, which can be handled by many ways. But consider a situation where you want to send a message without checking whether the system is currently available or not. You just want to send it and when the user starts his application on his system, he should get that message. There needs to be something between the two applications that can manage the communication and deal with these problems. One type of software that can overcome these issues is called a message queuing system. The message queuing system that is a companion to IIS 4.0 is called the Microsoft Message Queue System (MSMQ).

Why and when we need such functionality: Consider a situation where we need to process client requests through a number of customer care executives. We will use a web application to get requests from the client, and then store it in a database. Now we need to retrieve these requests and distribute to a number of executives. A restriction is the requests should not be processed from an outside machine. If a machine is inside the domain, then only should it be able to install the application and can process requests. Now, to implement this functionality, there are a number of ways. But we can implement the same functionality using MSMQ. In this article, I am not implementing the entire functionality, but a part of it. That is, we will implement the functionality of the messenger in which we can put a message in the queue and the receiver can receive it at any time when he gets online. Here is the diagram and the code…

An Idea!!!

ChatDiagram.jpg

In the above diagram, we can see that we will create a number of message queues for the number of users to receive messages in the queue. If C and B wants to send a message to A, then they will put that message in the queue that belongs to A, i.e., ‘QueueA’. And vice versa. An advantage of creating separate queues is that all users can put their messages in that queue and the receiver can receive that message any time when he gets online.

Chat.jpg

Writing a Message to a Queue

The entire code and comments are self explaining. The first step is to check whether there is a message queue present or not by using the current system name. If not, we create it. For creating a message queue, we use the following code:

C#
if (!MessageQueue.Exists(@"ServerName\QueueName"))
{
    MessageQueue.Create(@"ServerName\QueueName", false);
    MessageBox.Show("Queue named queuemsgs is created on your m/c");
}

By using the above code, we can create a message queue using the machine name. First, we need to check whether the queue is already present or not.

Here is the code for sending a message to the message queue. But before sending a message, you need to create message queues. One more thing is that you need to decide a server where all the queues will be maintained, and that system name has to be provided as “ServerName”.

C#
static string selectedmcname = "ServerName";
private void BtnSend_Click(object sender, EventArgs e)
{
    //The code for Sending message.
    try
    {
        MessageQueue msgQ_Send = new MessageQueue();

        if (ConB_SendTo.Text != "")
        {
            //Select User to which you want to send message.
            msgQ_Send.Path = @"FormatName:DIRECT=OS:" + ConB_SendTo.Text;
        } 
        else
        {
            //General queue for sending messages
            msgQ_Send.Path = @"FormatName:DIRECT=OS:" + Generalqueue;
        } 

        //Send all information that u want, along with the message
        RequestInformation objMsg = new RequestInformation();
        objMsg.Name = TxtYourName.Text;
        objMsg.Message = TxtSend.Text;

        //Bind your message with Message Class.
        System.Messaging.Message m = new System.Messaging.Message();
        m.Body = objMsg;
        m.Formatter = new BinaryMessageFormatter();
        m.AppSpecific = 34;

        //sending message along with other information. 
        //Second parameter we are passing is called 'LABEL'
        //By which we can send some more information 
        //so that one can use it farther for the implimentation
        //of functionality such as filteration of messages.
        msgQ_Send.Send(m, DateTime.Now.ToLongTimeString() + 
             "::" + System.Environment.MachineName);

        //see what message you sent.
        TxtMsg.Text += "\r\n" + Environment.MachineName + ": " + TxtSend.Text;

        TxtSend.Text = "";
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error");
    }
}

The RequestInformation class mentioned above is defined for storing all the information you want to send along with the message. The logic behind is that we can serialize that class object and then send it using binary serialization. That way, we can send more than one message, or a message along with other information at a time. Here is the class defined...

C#
using System;
using System.Collections.Generic;
using System.Text;

namespace MessageQueueDemo
{
    //Attribute must be added for mesioning class can be serialize
    [Serializable]
    public class RequestInformation
    {
        public RequestInformation()
        {
        }
        //one can add number of variables or inforation in this class 
        //like address, MobileNumber.
        public string Name;
    
        public string Message;
    }
}

The class should be marked as serialized. While defining a class, we can use private variables too, and some public methods for storing information.

Reading from Queue

This is a page load event. Here, we need to start a thread which will continuously look for new messages in the queue.

C#
private void ChatWindow_Load(object sender, EventArgs e)
{
    try
    {
        //List all Message Queue's available.
        MessageQueue[] queues = MessageQueue.GetPublicQueues();
        //Fill combo box with all queues.
        foreach (MessageQueue queue in MessageQueue.GetPublicQueues())
        {
            ConB_SendTo.Items.Add(queue.Path);
        }
    }

    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    //Start Thread which will keep track on incoming messages.
    Thread th = new Thread(GetMesqueue);
    th.Start();
}

Here is the method which has the functionality for receiving messages from the queue:

C#
private void GetMesqueue()
{
    //To avoid cross threading
    CheckForIllegalCrossThreadCalls = false;
    while (true)
    {
        try
        {
            //If message queue is not in the list then create it on server.
            if (!MessageQueue.Exists(ServerName + @"\" + Environment.MachineName))
            {
                MessageQueue.Create(ServerName + @"\" + Environment.MachineName);
            }
            //User can get messages from queue which belongs to his machine name.
            MessageQueue msgqueue_Get = new MessageQueue();
            msgqueue_Get.Path = @"FormatName:DIRECT=OS:" + 
                     ServerName + @"\" + Environment.MachineName;
            Type[] target = new Type[1];
            target[0] = typeof(string);

            //Time out is 2 seconds.
            System.Messaging.Message msg = msgqueue_Get.Receive(new TimeSpan(0, 0, 2));
            //Formatter for deserialization of message 
            msg.Formatter = new System.Messaging.BinaryMessageFormatter();

            //Deserialization of a message.
            RequestInformation info = (RequestInformation)msg.Body;
          
            TxtMsg.Text += "\r\n" + info.Name+" : "+info.Message;
        }
        catch (Exception ex)
        {
            //Check whether Queue is empty? if empty then go farther
            //if not then give a message bax with 
            //error message.
            if (ex.Message != "Timeout for the requested operation has expired.")
            {
                MessageBox.Show(ex.Message, "Error");
                break;
            }
        }
    }
}

Conclusion

This article is about creating a message queue to send messages to a number of users. No need to create or maintain separate XML files to send data; let Windows do the data transmission and maintaining the queues. We just need to create a queue and send the messages. We can go farther and implement it over HTTP.

Alternate Ideas

We may be familiar with the concept of the FileSystemWatcher class. By using this class, we can track the changes made in the directory or file. We can use XML files to store data or to share data. That file can be put in a shared folder. Thus, we can transfer messages using the XML file and the FileSystemWatcher. And finally, we have to do each and everything manually, which is a bulky task.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)