使用 MSMQ 聊天






2.91/5 (14投票s)
使用 MSMQ 实现两台机器之间的通信。
引言
这是一个用于局域网(LAN)中使用的聊天应用程序,它使用了 MSMQ。在该应用程序中,我们将设置一个服务器来维护所有消息,客户端机器可以发送或接收消息。
安装
在使用此应用程序之前,我们应该在服务器和客户端机器上安装 MSMQ。MSMQ 是 Microsoft Windows 提供的一种功能。在安装操作系统时,默认情况下它不会被安装;您需要从“控制面板”->“添加/删除程序”->“添加/删除 Windows 组件”->“消息队列”中手动安装它。
什么是 MSMQ?
MSMQ 是 Microsoft 的消息队列,它允许两台计算机之间进行通信。您可以发送和接收消息,而无需担心它们是否已送达另一台机器。MSMQ 允许将消息放入队列,如果用户当前不在线,消息将保留在队列中。一旦用户接收到消息,它就会被删除。在许多应用程序中,需要将数据或消息发送到另一个系统,这可以通过多种方式实现。但请考虑这样一种情况:您想发送一条消息,而不关心对方系统当前是否可用。您只想发送它,当用户在其系统上启动应用程序时,他应该能收到那条消息。需要在两个应用程序之间存在一个东西来管理通信并处理这些问题。一种可以克服这些问题的软件称为消息队列系统。与 IIS 4.0 配合使用的消息队列系统称为 Microsoft Message Queue System (MSMQ)。
为什么以及何时我们需要这样的功能:设想这样一种情况,我们需要通过多个客户服务代表来处理客户请求。我们将使用一个 Web 应用程序从客户端获取请求,然后将其存储在数据库中。现在,我们需要检索这些请求并将它们分发给多个代表。一个限制是这些请求不能从外部机器处理。只有当机器在域内时,它才应该能够安装应用程序并处理请求。现在,为了实现这个功能,有很多种方法。但是我们可以使用 MSMQ 来实现相同的功能。在本篇文章中,我不会实现全部功能,而只是实现其中的一部分。也就是说,我们将实现消息传递器的功能,我们可以将消息放入队列,接收者可以在他上线时随时接收到它。下面是图和代码…
一个想法!!!
在上图所示的流程中,我们可以看到我们将为多个用户创建消息队列以接收队列中的消息。如果 C 和 B 想发送消息给 A,那么他们会将消息放入属于 A 的队列,即“QueueA”。反之亦然。创建独立队列的一个优点是,所有用户都可以将他们的消息放入该队列,接收者可以在他上线时随时接收到该消息。
向队列写入消息
整个代码和注释都是自 explanatory 的。第一步是检查是否存在消息队列,通过使用当前系统名称来判断。如果不存在,我们就创建它。要创建消息队列,我们使用以下代码:
if (!MessageQueue.Exists(@"ServerName\QueueName"))
{
MessageQueue.Create(@"ServerName\QueueName", false);
MessageBox.Show("Queue named queuemsgs is created on your m/c");
}
使用上述代码,我们可以使用机器名称创建消息队列。首先,我们需要检查队列是否已存在。
这是发送消息到消息队列的代码。但在发送消息之前,您需要创建消息队列。还有一点是,您需要决定一个服务器来维护所有队列,并且必须将该系统名称提供为“ServerName
”。
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");
}
}
上面提到的 `RequestInformation` 类是为了存储您想随消息一起发送的所有信息而定义的。其背后的逻辑是,我们可以序列化该类对象,然后通过二进制序列化来发送它。这样,我们可以一次发送多条消息,或者发送一条消息以及其他信息。下面是类的定义…
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;
}
}
该类应标记为可序列化。在定义类时,我们也可以使用私有变量,以及一些公共方法来存储信息。
从队列读取
这是一个页面加载事件。在这里,我们需要启动一个线程,该线程将不断地检查队列中是否有新消息。
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();
}
这是具有从队列接收消息功能的方法
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;
}
}
}
}
结论
本文档是关于创建一个消息队列以将消息发送给多个用户的。无需创建或维护单独的 XML 文件来发送数据;让 Windows 来处理数据传输和队列维护。我们只需要创建队列并发送消息。我们可以进一步将其实现为通过 HTTP 传输。
备选方案
我们可能熟悉 `FileSystemWatcher` 类的概念。通过使用这个类,我们可以跟踪目录或文件所做的更改。我们可以使用 XML 文件来存储数据或共享数据。该文件可以放在共享文件夹中。这样,我们就可以通过 XML 文件和 `FileSystemWatcher` 来传输消息。最后,我们必须手动完成所有事情,这是一项繁琐的任务。