Message Queuing(MSMQ)学习之旅(一)——基本概念

本文介绍了Microsoft消息队列(MSMQ)的概念及其优势,详细解释了如何在环境中配置MSMQ,并提供了创建和使用公共及私有消息队列的方法。此外,还概述了消息队列的操作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.MSMQ是什么?
(来源:百度百科)
Message Queue(微软消息队列)是在多个不同的应用之间实现相互通信的一种异步传输模式,相互通信的应用可以分布于同一台机器上,也可以分布于相连的网络空间中的任一位置。它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中;本地或者是异地的消息接收程序再从该队列中取出发给它的消息进行处理。
2.MSMQ的好处

比起TCP/IP通讯,我觉得MSMQ的好处在能支持两个应用程序之间的离线通讯,接收方和发送方不需要同时运行,发送方可以先把消息发出来,过一段时间,接收方也能接收得到消息。

3.环境的配置

1.在Services里面启动Message Queuing服务。
2.打开Start->Administrative Tools->Computer Management.在Services and Applications下面的Message Queuing里面能够看到程序中现有的Queue。
3.用C++写Message Queue的应用程序,需要包含头文件mq.h和lib库mqrt.lib。

4.Message Queue的分类

其中Public Queue和Private Queue是由应用程序创建的,或者是在Computer Management里面也可以手动建。System Queue都是由Message Queuing建的,应用程序可以读取,不能创建。

5.Message Queue操作的基本流程

Message Queue一般需要两个应用程序,一个应用程序是Message的发送方,一个应用程序是Message的接收方。
发送方:
1.创建并以发送的方式打开一个Message Queue
2.打包消息并发送
3.关闭Message Queue

接收方:
1.以接收或读取的方式打开一个Message Queue
2.接收消息并进行处理
3.关闭Message Queue

 

### 如何在 C++ 中集成和使用 Microsoft Message Queue (MSMQ) Microsoft Message Queue (MSMQ)种消息队列技术,允许应用程序通过发送和接收消息来进行通信。它支持跨网络的消息传递,并能在不可靠的环境中提供可靠的消息交付机制。 以下是关于如何在 C++ 中集成和使用 MSMQ 的详细介绍: #### 1. 安装和配置 MSMQ 为了能够在 Windows 上使用 MSMQ,需要先安装并启用该服务。可以通过以下步骤完成: - 打开“控制面板” -> “程序和功能” -> “启用或关闭 Windows 功能”。 - 勾选“Message Queuing”及其子项[^3]。 此外,在进行远程调试时需要注意些额外的安全设置,例如取消服务器安全性的限制以及为队列分配适当的权限[^3]。 #### 2. 编程接口概述 MSMQ 提供了个 COM 接口用于开发人员编写客户端应用。C++ 开发者通常会利用 MFC 或 ATL 库来简化对 COM 对象的操作过程。主要涉及以下几个类: - `IMSMQQueue`:表示单个消息队列实例。 - `IMSMQMessage`:定义了条具体的消息对象。 - `IMSMQCoordinatedTransactionDispenser` 和其他事务相关组件(可选)。 #### 3. 创建个简单的消息发送与接收示例 下面是完整的 C++ 示例代码展示如何向本地公共队列发送条测试消息再将其读回显示出来。 ```cpp #include <windows.h> #include <mq.h> // MSMQ header file #include <atlbase.h> // For CComPtr #include <iostream> // Initialize COM library before using any MSMQ functions. void InitCOM() { HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { std::cerr << "Failed to initialize COM library." << std::endl; exit(1); } } int main() { try { InitCOM(); // Define queue path name and create a pointer to IMSMQQueue interface. const wchar_t* QUEUE_PATHNAME = L".\\public$\MyTestQueue"; CComPtr<IMSMQQueueInfo> spQueueInfo; HRESULT hr = spQueueInfo.CoCreateInstance(CLSID_MSMQQueueInfo); if (SUCCEEDED(hr)) { spQueueInfo->put_PathName(QUEUE_PATHNAME); VARIANT vOpenFlags, vAccess, vShareMode; VariantInit(&vOpenFlags), VariantInit(&vAccess), VariantInit(&vShareMode); vOpenFlags.vt = VT_I4; vOpenFlags.lVal = MQ_SEND_ACCESS | MQ_RECEIVE_ACCESS; vAccess.vt = VT_UI4; vAccess.ulVal = MQ_DENY_NONE; vShareMode.vt = VT_UI4; vShareMode.ulVal = 0; CComPtr<IMSMQQueue> spQueue; hr = spQueueInfo->Open(vOpenFlags, vAccess, &spQueue); if (SUCCEEDED(hr)) { // Create message object CComPtr<IMSMQMessage> spMsg; hr = spMsg.CoCreateInstance(__uuidof(MSMQMessage)); if (SUCCEEDED(hr)) { BSTR bstrLabel = SysAllocString(L"Test Label"); spMsg->put_Label(bstrLabel); SAFEARRAY *psaBody = SafeArrayCreateVector(VT_UI1, 0, strlen("Hello MSMQ!")); char data[] = "Hello MSMQ!"; memcpy(SafeArrayGetPV(psaBody, NULL), data, sizeof(data)-1); spMsg->put_Body(psaBody); SysFreeString(bstrLabel); SafeArrayDestroy(psaBody); // Send the message spMsg->Send(spQueue); printf("Message sent successfully.\n"); // Receive the same message back immediately as an example of receiving messages CComVariant varReceiveTimeout; varReceiveTimeout.vt = VT_I4; varReceiveTimeout.intVal = 5000; // Timeout set at 5 seconds CComPtr<IMSMQMessage> spReceivedMsg; hr = spQueue->Receive(varReceiveTimeout, NULL, NULL, NULL, &spReceivedMsg); if (SUCCEEDED(hr)) { long cbDataSize; BYTE* pDataBuffer; spReceivedMsg->get_Body(&psaBody); SafeArrayAccessData(psaBody, reinterpret_cast<void**>(&pDataBuffer)); SafeArrayGetUBound(psaBody, 1, &cbDataSize); for(int i=0;i<=cbDataSize;i++) putchar(*(pDataBuffer+i)); puts(""); SafeArrayUnaccessData(psaBody); SafeArrayDestroy(psaBody); } else { printf("No message received within timeout period or error occurred during reception."); } spQueue->Close(); } } else { printf("Could not open specified queue %ls\n", QUEUE_PATHNAME); } } CoUninitialize(); } catch (...) { std::cout << "An exception was caught!" << std::endl; } return 0; } ``` 以上代码展示了基本的功能实现方法,包括初始化 COM 环境、打开目标队列、构建消息体并通过指定路径名发送出去;同时也演示了即时获取刚发出的信息作为验证手段之。 #### 注意事项 - **异常处理**:实际项目中应更加注重各种可能发生的错误情况下的优雅降级策略。 - **性能优化**:当面对高吞吐量需求场景下考虑采用批量操作等方式提升效率。 - **安全性考量**:确保只有授权用户才能访问敏感数据所在的队列资源[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值