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++下使用邮槽实现进程间通信的更多相关文章

  1. [Win]进程间通信——邮槽Mailslot

    进程间通信 进程的地址空间是私有的.出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义.但是在一些具体的应用情况下需要多个进行相互配合 ...

  2. Windows网络编程笔记3 ---- 邮槽和命名管道

    邮槽和命名管道的使用方法也很简单,只需几个有限的函数就可以实现双方的通信. 第三.邮槽 邮槽----进程间通信机制. 通过邮槽客户进程可以将消息通过广播给一个或多个服务进程.这是一个单向通信机制,缺点 ...

  3. [C++] socket -7 [邮槽]

    ::利用邮槽实现windons进程通信 ::一般情况下CreateMailslot()常被使用在进程通信的服务器上,在客户端则是用函数CreateFile()打开指定的邮槽之后进行相关的操作. ::将 ...

  4. window API一天一练之邮槽

    邮槽通信的进程分为服务端和客户端.服务端创建邮槽,客户端通过邮槽名打开邮槽,获得句柄后可以向邮槽写数据. 邮槽通信是单向通信,只能由客户端向服务端发送数据.下面来看看有关邮槽的几个API HANDLE ...

  5. 邮槽 匿名管道 命名管道 剪贴板 进程通讯 转自http://www.cnblogs.com/kzloser/archive/2012/11/04/2753367.html#

    邮槽 通信流程: 服务器 客户端 注意: 邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输 邮槽可以实现一对多的单向通信,我们可以利用这个特点编写一个网络会议通知系统,而且实现这一的系 ...

  6. 【IPC进程间通讯之中的一个】邮槽MailSlot

    IPC进程间通信+邮槽MailSlot                IPC(Inter-Process Communication.进程间通信).        现代计算机採用虚拟内存机制,为进程提 ...

  7. c++下使用命名管道实现进程间通信

    前面已经使用邮槽实现过进程间通信:http://www.cnblogs.com/jzincnblogs/p/5192654.html ,这里使用命名管道实现进程间通信. 与邮槽不同的是,命名管道在进程 ...

  8. windows 邮槽mailslot 在服务程序内建立后客户端无权限访问(GetLastError() == 5)的问题

    邮槽创建在服务程序内,可以创建成功, 但外部客户端连接时 m_hMailslot = CreateFile("\\\\.\\mailslot\\zdpMailslot",GENER ...

  9. [转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile

    http://blog.csdn.net/stpeace/article/details/39534361 进程间的通信方式有很多种, 上次我们说了最傻瓜的“共享外存/文件”的方法. 那么, 在本文中 ...

随机推荐

  1. JAVA面试题整理(2)-多线程/并发

    1.synchronized 的实现原理以及锁优化? 在JDK 5之前Java语言是靠synchronized关键字保证同步的.使用synchronized 关键字定义同步方法,或者在方法中使用syn ...

  2. Spring七大框架

    Spring Core:最基础部分,提供IOC和依赖注入.基础概念是BeanFactory,提供对Factory模式的经典实现,这样来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关 ...

  3. 配置linux使用mail发送邮件到163邮箱

    1.进行配置 yum install -y mailx /etc/mail.rc添加对163的授权: ##########config 163 mail############set from=jso ...

  4. 20145314郑凯杰 《Java程序设计》第9周学习总结 积极主动敲代码

    20145314郑凯杰 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 ①JDBC(Java DataBase Connectivity) 即java数据库连接,是一种用于 ...

  5. MyBatis如何返回自增的ID

    <insert id="insertTable" parameterType="com.infohold.city.map.model.CheckTemplateM ...

  6. Http中Get和Post的区别(转载)

    在B/S应用程序中,前台与后台的数据交互,都是通过HTML中Form表单完成的.Form提供了两种数据传输的方式——get和post.虽然它们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可 ...

  7. Jenkins FreeStyle or Pipeline Job

    FreeStyle Job: 1. 需要在页面添加模块配置项与参数完成配置 2. 每个Job仅能实现一个开发功能 3. 无法将配置代码化,不利于Job配置迁移与版本控制 4. 逻辑相对简单,无额外学习 ...

  8. JAVA链接数据库

    链接:http://www.cnblogs.com/centor/p/6142775.html 开发工具: MyEclipse MySQL JDBC驱动:mysql-connector-java-5. ...

  9. Hue的安装与部署

    Hue的安装与部署 hadoop hue Hue 简介 Hue是一个开源的Apache Hadoop UI系统,最早是由Cloudera Desktop演化而来,由Cloudera贡献给开源社区,它是 ...

  10. 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛-A banana·

    2017-09-09 16:41:28 writer:pprp 题意很好理解就不说了,实现比较清晰,选择邻接表来做 但是我用的是链表来实现的,所以导致出现了很多问题,最后卡的最长时间的一个问题是 应该 ...