Windows API提供了邮槽和命名管道两种机制来实现进程间通信,在这里使用C++实现邮槽。
邮槽是Windows提供的一种进程间单向通信的机制,进程中的一方只能读取(或写入)数据,而另一方只能写入(或读取)数据。这种进程间的通信可以发生在本地或者网络之中。而在使用邮槽之前,服务器端必须先创建邮槽,创建的函数原型如下:
1 HANDLE WINAPI CreateMailslot(
2 _In_ LPCTSTR lpName,
3 _In_ DWORD nMaxMessageSize,
4 _In_ DWORD lReadTimeout,
5 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
6 );
其中参数lpName表示邮槽的名称。邮槽名称的格式为"\.\mailslot\YourMailslotName",其中YourMailslotName由用户指定。需要注意的是,在实际编码中反斜杠需要转义;参数nMaxMessageSize表示发送的消息大小的最大值,若设置为0则表示大小为任意值。(实际上邮槽能传输的数据非常小,一般400KB,若数据过大,邮槽可能无法正常工作);参数lReadTimeout表示读取操作的超时时间;参数lpSecurityAttributes表示邮槽的安全属性,置为NULL表示使用默认的安全属性。
客户端在使用邮槽前必须先打开邮槽,通过函数CreateFile()实现,函数原型如下:
1 HANDLE WINAPI CreateFile(
2 _In_ LPCTSTR lpFileName,
3 _In_ DWORD dwDesiredAccess,
4 _In_ DWORD dwShareMode,
5 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
6 _In_ DWORD dwCreationDisposition,
7 _In_ DWORD dwFlagsAndAttributes,
8 _In_opt_ HANDLE hTemplateFile
9 );
参数的具体设置方法可参考MSDN给出的解释:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
需要注意的是,指定要打开的邮槽时,若程序是在不同主机上运行的,邮槽名称中的点号"."需要改成对方主机的名称。
在实际的编程过程中,对邮槽的操作与文件一样,都是通过调用函数ReadFile()和WriteFile()实现的,函数原型如下:
1 BOOL WINAPI ReadFile(
2 _In_ HANDLE hFile,
3 _Out_ LPVOID lpBuffer,
4 _In_ DWORD nNumberOfBytesToRead,
5 _Out_opt_ LPDWORD lpNumberOfBytesRead,
6 _Inout_opt_ LPOVERLAPPED lpOverlapped
7 );
8
9 BOOL WINAPI WriteFile(
10 _In_ HANDLE hFile,
11 _In_ LPCVOID lpBuffer,
12 _In_ DWORD nNumberOfBytesToWrite,
13 _Out_opt_ LPDWORD lpNumberOfBytesWritten,
14 _Inout_opt_ LPOVERLAPPED lpOverlapped
15 );
其中参数lpNumberOfBytesWritten是一个指向DWORD类型的指针,表示实际读取/写入的字节数。
最终实现的代码如下,实现面向对象的方法实现:
服务器端:
1 //header.h
2 #ifndef HEADER_H
3 #define HEADER_H
4
5 #include <windows.h>
6
7 #define BUFFER_SIZE 1024
8
9 class MailServer
10 {
11 public:
12 MailServer();
13 MailServer(const MailServer &) = delete;
14 MailServer & operator=(const MailServer &) = delete;
15 ~MailServer();
16 void ReadMail();
17 private:
18 HANDLE h_mail;
19 char buffer[BUFFER_SIZE];
20 DWORD exact_read_num; //指向实际读取的字节数的指针
21 };
22
23 #endif
1 //definition.cpp
2 #include "header.h"
3 #include <iostream>
4
5 MailServer::MailServer()
6 {
7 //邮槽的命名格式为"\\.\mailslot\YourMailslotName",反斜杠需要转义,采用非阻塞式读取方法
8 h_mail = ::CreateMailslot("\\\\.\\mailslot\\MyMailSlot", 0, 0, nullptr);
9 if (h_mail == INVALID_HANDLE_VALUE)
10 {
11 std::cerr << "Failed to create a mailslot!\n";
12 ::system("pause");
13 exit(1);
14 }
15 else
16 {
17 std::cout << "Mailslot created successfully..." << std::endl;
18 }
19 }
20
21 MailServer::~MailServer()
22 {
23 ::CloseHandle(h_mail);
24 std::cout << "Mailslot closed..." << std::endl;
25 }
26
27 void MailServer::ReadMail()
28 {
29 std::cout << "Reading mail from mailslot..." << std::endl;
30 while (true)
31 {
32 if (::ReadFile(h_mail, buffer, BUFFER_SIZE, &exact_read_num, nullptr))
33 {
34 std::cout << "New mail: " << buffer << std::endl;
35 }
36 }
37 }
1 //server.cpp
2 #include "header.h"
3
4 int main()
5 {
6 MailServer mail_svr;
7 mail_svr.ReadMail();
8 system("pause");
9 return 0;
10 }
客户端:
1 //header.h
2 #ifndef HEADER_H
3 #define HEADER_H
4
5 #include "windows.h"
6
7 #define BUFFER_SIZE 1024
8
9 class MailClient
10 {
11 public:
12 MailClient();
13 MailClient(const MailClient &) = delete;
14 MailClient & operator=(const MailClient &) = delete;
15 ~MailClient();
16 void SendMail();
17 private:
18 HANDLE h_mail;
19 char buffer[BUFFER_SIZE];
20 DWORD exact_write_num;
21 };
22
23 #endif
1 //definition.cpp
2 #include "header.h"
3 #include <iostream>
4
5 MailClient::MailClient()
6 {
7 h_mail = ::CreateFile("\\\\.\\mailslot\\MyMailSlot", GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
8 if (h_mail == INVALID_HANDLE_VALUE)
9 {
10 std::cerr << "Failed to create a mailslot!\n";
11 system("pause");
12 exit(1);
13 }
14 else
15 {
16 std::cout << "Mailslot created successfully..." << std::endl;
17 }
18 }
19
20 MailClient::~MailClient()
21 {
22 ::CloseHandle(h_mail);
23 std::cout << "Mailslot closed..." << std::endl;
24 }
25
26 void MailClient::SendMail()
27 {
28 while (true)
29 {
30 std::cout << "Please write a mail: " << std::flush;
31 std::cin.getline(buffer, BUFFER_SIZE);
32 if (strcmp(buffer, "exit") == 0)
33 {
34 std::cout << "User requests to close the mailslot..." << std::endl;
35 break;
36 }
37 else
38 {
39 if (::WriteFile(h_mail, buffer, BUFFER_SIZE, &exact_write_num, nullptr))
40 {
41 std::cout << "Mail sent successfully..." << std::endl;
42 }
43 else
44 {
45 std::cerr << "Failed to send the mail...\n";
46 system("pause");
47 exit(1);
48 }
49 }
50 }
51 }
1 #include "header.h"
2
3 int main()
4 {
5 MailClient mail_clt;
6 mail_clt.SendMail();
7 system("pause");
8 return 0;
9 }
原文链接: https://www.cnblogs.com/jzincnblogs/p/5192654.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/228762
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!