c++下使用邮槽实现进程间通信
Windows API提供了邮槽和命名管道两种机制来实现进程间通信,在这里使用C++实现邮槽。
邮槽是Windows提供的一种进程间单向通信的机制,进程中的一方只能读取(或写入)数据,而另一方只能写入(或读取)数据。这种进程间的通信可以发生在本地或者网络之中。而在使用邮槽之前,服务器端必须先创建邮槽,创建的函数原型如下:
HANDLE WINAPI CreateMailslot(
_In_ LPCTSTR lpName,
_In_ DWORD nMaxMessageSize,
_In_ DWORD lReadTimeout,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
其中参数lpName表示邮槽的名称。邮槽名称的格式为"\\.\mailslot\YourMailslotName",其中YourMailslotName由用户指定。需要注意的是,在实际编码中反斜杠需要转义;参数nMaxMessageSize表示发送的消息大小的最大值,若设置为0则表示大小为任意值。(实际上邮槽能传输的数据非常小,一般400KB,若数据过大,邮槽可能无法正常工作);参数lReadTimeout表示读取操作的超时时间;参数lpSecurityAttributes表示邮槽的安全属性,置为NULL表示使用默认的安全属性。
客户端在使用邮槽前必须先打开邮槽,通过函数CreateFile()实现,函数原型如下:
HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
参数的具体设置方法可参考MSDN给出的解释:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
需要注意的是,指定要打开的邮槽时,若程序是在不同主机上运行的,邮槽名称中的点号"."需要改成对方主机的名称。
在实际的编程过程中,对邮槽的操作与文件一样,都是通过调用函数ReadFile()和WriteFile()实现的,函数原型如下:
BOOL WINAPI ReadFile(
_In_ HANDLE hFile,
_Out_ LPVOID lpBuffer,
_In_ DWORD nNumberOfBytesToRead,
_Out_opt_ LPDWORD lpNumberOfBytesRead,
_Inout_opt_ LPOVERLAPPED lpOverlapped
); BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
其中参数lpNumberOfBytesWritten是一个指向DWORD类型的指针,表示实际读取/写入的字节数。
最终实现的代码如下,实现面向对象的方法实现:
服务器端:
//header.h
#ifndef HEADER_H
#define HEADER_H #include <windows.h> #define BUFFER_SIZE 1024 class MailServer
{
public:
MailServer();
MailServer(const MailServer &) = delete;
MailServer & operator=(const MailServer &) = delete;
~MailServer();
void ReadMail();
private:
HANDLE h_mail;
char buffer[BUFFER_SIZE];
DWORD exact_read_num; //指向实际读取的字节数的指针
}; #endif
//definition.cpp
#include "header.h"
#include <iostream> MailServer::MailServer()
{
//邮槽的命名格式为"\\.\mailslot\YourMailslotName",反斜杠需要转义,采用非阻塞式读取方法
h_mail = ::CreateMailslot("\\\\.\\mailslot\\MyMailSlot", , , nullptr);
if (h_mail == INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to create a mailslot!\n";
::system("pause");
exit();
}
else
{
std::cout << "Mailslot created successfully..." << std::endl;
}
} MailServer::~MailServer()
{
::CloseHandle(h_mail);
std::cout << "Mailslot closed..." << std::endl;
} void MailServer::ReadMail()
{
std::cout << "Reading mail from mailslot..." << std::endl;
while (true)
{
if (::ReadFile(h_mail, buffer, BUFFER_SIZE, &exact_read_num, nullptr))
{
std::cout << "New mail: " << buffer << std::endl;
}
}
}
//server.cpp
#include "header.h" int main()
{
MailServer mail_svr;
mail_svr.ReadMail();
system("pause");
return ;
}
客户端:
//header.h
#ifndef HEADER_H
#define HEADER_H #include "windows.h" #define BUFFER_SIZE 1024 class MailClient
{
public:
MailClient();
MailClient(const MailClient &) = delete;
MailClient & operator=(const MailClient &) = delete;
~MailClient();
void SendMail();
private:
HANDLE h_mail;
char buffer[BUFFER_SIZE];
DWORD exact_write_num;
}; #endif
//definition.cpp
#include "header.h"
#include <iostream> MailClient::MailClient()
{
h_mail = ::CreateFile("\\\\.\\mailslot\\MyMailSlot", GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (h_mail == INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to create a mailslot!\n";
system("pause");
exit();
}
else
{
std::cout << "Mailslot created successfully..." << std::endl;
}
} MailClient::~MailClient()
{
::CloseHandle(h_mail);
std::cout << "Mailslot closed..." << std::endl;
} void MailClient::SendMail()
{
while (true)
{
std::cout << "Please write a mail: " << std::flush;
std::cin.getline(buffer, BUFFER_SIZE);
if (strcmp(buffer, "exit") == )
{
std::cout << "User requests to close the mailslot..." << std::endl;
break;
}
else
{
if (::WriteFile(h_mail, buffer, BUFFER_SIZE, &exact_write_num, nullptr))
{
std::cout << "Mail sent successfully..." << std::endl;
}
else
{
std::cerr << "Failed to send the mail...\n";
system("pause");
exit();
}
}
}
}
#include "header.h" int main()
{
MailClient mail_clt;
mail_clt.SendMail();
system("pause");
return ;
}
c++下使用邮槽实现进程间通信的更多相关文章
- [Win]进程间通信——邮槽Mailslot
进程间通信 进程的地址空间是私有的.出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义.但是在一些具体的应用情况下需要多个进行相互配合 ...
- Windows网络编程笔记3 ---- 邮槽和命名管道
邮槽和命名管道的使用方法也很简单,只需几个有限的函数就可以实现双方的通信. 第三.邮槽 邮槽----进程间通信机制. 通过邮槽客户进程可以将消息通过广播给一个或多个服务进程.这是一个单向通信机制,缺点 ...
- [C++] socket -7 [邮槽]
::利用邮槽实现windons进程通信 ::一般情况下CreateMailslot()常被使用在进程通信的服务器上,在客户端则是用函数CreateFile()打开指定的邮槽之后进行相关的操作. ::将 ...
- window API一天一练之邮槽
邮槽通信的进程分为服务端和客户端.服务端创建邮槽,客户端通过邮槽名打开邮槽,获得句柄后可以向邮槽写数据. 邮槽通信是单向通信,只能由客户端向服务端发送数据.下面来看看有关邮槽的几个API HANDLE ...
- 邮槽 匿名管道 命名管道 剪贴板 进程通讯 转自http://www.cnblogs.com/kzloser/archive/2012/11/04/2753367.html#
邮槽 通信流程: 服务器 客户端 注意: 邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输 邮槽可以实现一对多的单向通信,我们可以利用这个特点编写一个网络会议通知系统,而且实现这一的系 ...
- 【IPC进程间通讯之中的一个】邮槽MailSlot
IPC进程间通信+邮槽MailSlot IPC(Inter-Process Communication.进程间通信). 现代计算机採用虚拟内存机制,为进程提 ...
- c++下使用命名管道实现进程间通信
前面已经使用邮槽实现过进程间通信:http://www.cnblogs.com/jzincnblogs/p/5192654.html ,这里使用命名管道实现进程间通信. 与邮槽不同的是,命名管道在进程 ...
- windows 邮槽mailslot 在服务程序内建立后客户端无权限访问(GetLastError() == 5)的问题
邮槽创建在服务程序内,可以创建成功, 但外部客户端连接时 m_hMailslot = CreateFile("\\\\.\\mailslot\\zdpMailslot",GENER ...
- [转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile
http://blog.csdn.net/stpeace/article/details/39534361 进程间的通信方式有很多种, 上次我们说了最傻瓜的“共享外存/文件”的方法. 那么, 在本文中 ...
随机推荐
- 20145314郑凯杰 《Java程序设计》实验五 实验报告
20145314郑凯杰 <Java程序设计>实验五 实验报告 实验搭档王亦徐:http://www.cnblogs.com/1152wyx/p/5471524.html 实验要求 完成实验 ...
- Win7旗舰版中的IIS配置asp.net 完美通过版,附代码 以及出现的 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\8d57d
先解决问题:“c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\8d57d 图: 其他的解决方案 ...
- 同余定理简单应用 - poj2769 - hdu 1021 - hdu 2035
同余问题 基本定理: 若a,b,c,d是整数,m是正整数, a = b(mod m), c = d(mod m) a+c = b+c(mod m) ac = bc(mod m) ax+cy = bx+ ...
- Jenkins-Kubernetes-docker-自动发布
使用的是Jenkins pipeline: 这里只是做了更新,没有创建,没有借助helm等工具,先用着,以后再研究. pipeline { agent any stages { stage(" ...
- geoserver源码学习与扩展——增加服务接口
参看:http://www.cnblogs.com/sillyemperor/archive/2011/01/11/1929420.html 上文写的很详细了.
- python2.7.10 VS2015编译方法
打开 Python-2.7.10\PCbuild目录 然后设置只编译python和pythoncore: 好了,编译试一试. 出现了好几个错误.由于 VS2015 取消了 timezone 的定义,改 ...
- angular js实现开关效果
功能:实现点击排序,再点击排倒序. 实现方法如下 方法一:定义变量实现点击切换true或false,代码为: $scope.lidata = [ {"name ...
- 1-15-2-RAID5 企业级RAID磁盘阵列的搭建(RAID1、RAID5、RAID10)
RAID5的搭建 第一步:添加四个磁盘,开机并检查(略过) 第二步:使用fdisk命令分别对四个磁盘进行分区,效果如下图: 第三步:使用mdadm命令创建RAID5磁盘阵列 [root@localho ...
- C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 06)
----------------------------------------- go 并发 // 注解:go 语言天生为程序并发所设计,可以说go的强项就是在cpu并发上的处理. // go 语言 ...
- Back Track5学习笔记
1.BT5默认用户名:root.密码:toor(公司是yeslabccies) 2.进入图形化界面命令:startx 3.更改密码:sudo passwd root 扫描工具 第一部分网络配置: 4. ...