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 进程间的通信方式有很多种, 上次我们说了最傻瓜的“共享外存/文件”的方法. 那么, 在本文中 ...
随机推荐
- clientWidth offsetWidth scrollWidth
网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offset ...
- 20145313Java第一次实验
实验内容 1.JVM.JRE.JDK的安装位置与区别: 2.命令行运行javac:java:javac -cp; java -cp: 3.PATH,CLASSPATH,SOURCEPATH的设定方法与 ...
- C++中的指针和数组
最近看C++编程思想,看到第十三章动态内存管理的时候把自己给绕进去了,主要是在数据和指针这块弄混了.现在把找到的一些资料总结如下: 1. 数组是数组,指针是指针,两者并不等价: 2.数组在作为左值的时 ...
- centos7.1 从源码升级安装Python3.5.2
http://blog.csdn.net/tengyunjiawu_com/article/details/53535153 centos7.1 从源码升级安装Python3.5.2(我写的,请大家度 ...
- Nginx 与 tomcat 部署网站
http://www.blogjava.net/libin2722/articles/355631.html http://congpeixue.iteye.com/blog/255011 keepa ...
- Memcached gets 命令
Memcached gets 命令获取带有 CAS 令牌存 的 value(数据值) ,如果 key 不存在,则返回空. 语法: gets 命令的基本语法格式如下: gets key 多个 key 使 ...
- thinkphp 模板中得到controller name,得到当前文件路径
<li><a href="/Admin/account" <eq name="Think.CONTROLLER_NAME" value= ...
- 【转】由浅入深探究mysql索引结构原理、性能分析与优化
摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1.简单介绍B-tree B+ tree树 2.MyisAM索引结构 3.Annode索引结构 4.MyisAM索引与Inno ...
- java socket 判断Socket连接失效
要判断socket连接链路是否可用时,不能通过socket.isClosed() 和 socket.isConnected() 方法判断,要通过心跳包 socket.sendUrgentData(0x ...
- C++ 线程的创建、挂起、唤醒和结束 &&&& 利用waitForSingleObject 函数陷入死锁的问题解决
最近在写一个CAN总线的上位机软件,利用CAN转USB的设备连到电脑上,进行数据的传输.在接收下位机发送的数据的时候采用的在线程中持续接收数据. 1.在连接设备的函数中,开启线程. ,CREATE_S ...