17 MFC进程通信

news2024/11/27 1:40:55

文章目录

  • 剪切板
  • 管道
    • 匿名管道
      • 父进程写入数据子进程读出数据
    • 命名管道
  • 邮槽
    • 邮槽服务器
    • 邮槽客户端

剪切板

设置界面
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

发送

//设置剪切板数据
void CClipboardDlg::OnBnClickedBtnSend()
{
	UpdateData(TRUE);
	if (m_strSend.IsEmpty())
	{
		MessageBox(L"请输入需要设置的文本", L"提示");
		return;
	}

	//打开剪切板
	if (FALSE == OpenClipboard())
	{
		CString str;
		str.Format(L"打开剪切板失败,错误代号:%d", GetLastError());
		MessageBox(str);
		return;
	}

	//清空剪切板
	EmptyClipboard();
	//在全局堆申请一块内存
	HGLOBAL hClip=GlobalAlloc(GMEM_MOVEABLE,m_strSend.GetLength()*2+1);
	//对全局堆内存枷锁
	TCHAR* pBuffer=(TCHAR*)GlobalLock(hClip);
	//清空内存
	ZeroMemory(pBuffer, m_strSend.GetLength() * 2 + 1);
	memcpy(pBuffer, m_strSend.GetBuffer(), m_strSend.GetLength() * 2 + 1);

	//解锁
	GlobalUnlock(hClip);

	//设置剪切板数据
	SetClipboardData(CF_UNICODETEXT, hClip);
	//关闭剪切板,一定要关闭剪切板
	CloseClipboard();
}

从剪切版里面接收数据

void CClipboardDlg::OnBnClickedBtnReceive()
{
	//打开剪切板
	if (FALSE == OpenClipboard())
	{
		CString str;
		str.Format(L"打开剪切板失败,错误代号:%d", GetLastError());
		MessageBox(str);
		return;
	}
	//检查截切版中是否有我们指定格式的数据
	if (IsClipboardFormatAvailable(CF_UNICODETEXT))
	{
		//得到剪切板数据
		HANDLE hClip=GetClipboardData(CF_UNICODETEXT);
		//把句柄转换为指针
		TCHAR* pBuffer=(TCHAR*)GlobalLock(hClip);
		m_strRecv = pBuffer;
		//解锁
		GlobalUnlock(hClip);
		UpdateData(FALSE);
	}
	//关闭剪切板,一定要关闭剪切板
	CloseClipboard();
}

请添加图片描述

管道

命名管道(Named Pipe)和匿名管道(Anonymous Pipe)都是用于进程间通信的机制,但它们有一些区别。

命名管道(Named Pipe):

命名管道是具有唯一名称的管道,可以通过该名称在不同进程之间进行通信。
命名管道可以在本地机器上的不同进程之间进行通信,也可以在网络上的不同计算机之间进行通信。
命名管道支持全双工通信,可以同时进行读取和写入操作。
命名管道可以被多个进程打开和使用,允许多个读取者和写入者同时进行操作。
命名管道通常用于需要持久性连接和长期通信的场景,例如服务器和客户端之间的通信。

匿名管道(Anonymous Pipe):

匿名管道是一种无名称的管道,仅限于在父子进程或者兄弟进程之间进行通信。
匿名管道只能在同一个计算机上的相关进程之间进行通信,不能跨网络使用。
匿名管道是单向的,只能支持单向的数据流传输,例如从父进程到子进程。
匿名管道一般用于简单的进程间通信需求,例如父进程将数据传递给子进程进行处理。

匿名管道

父进程
在这里插入图片描述
子进程
在这里插入图片描述

子进程的*.exe放到父进程中
在这里插入图片描述

父进程启动子进程

//创建子进程
void CParentPipDlg::OnBnClickedBtnCreate()
{
	//创建匿名管道
	//第1,2个参数:读写句柄
	//第3个参数:安全描述符
	SECURITY_ATTRIBUTES sa;
	sa.bInheritHandle = TRUE;//子进程继承父进程的句柄
	sa.lpSecurityDescriptor = NULL;//安全描述符
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);//结构体大小
	//第4个参数:缓冲区大小
	if (!CreatePipe(&m_hRead, &m_hWrite, &sa, 0))
	{
		MessageBox(L"创建匿名管道失败",L"提示");
		return;
	}



	TCHAR szCmdLine[MAX_PATH] = L"subPip.exe";
	//启动信息
	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESTDHANDLES;//标准输入输出
	si.hStdInput = m_hRead;//标准输入
	si.hStdOutput = m_hWrite;//写入
	si.hStdError = GetStdHandle(STD_ERROR_HANDLE);//标准输入输出错误句柄
	//进程信息
	PROCESS_INFORMATION pi = { 0 };

	if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si,&pi))
	{
		CloseHandle(m_hRead);
		CloseHandle(m_hWrite);
		m_hRead = NULL;
		m_hWrite = NULL;
		MessageBox(L"创建子进程失败", L"提示");
		return;
	}
}

请添加图片描述

父进程写入数据子进程读出数据

父进程写入数据

//写入数据
void CParentPipDlg::OnBnClickedBntWrite()
{
	wchar_t buffer[100]=L"我是父进程";
	//向文件或者其他输出设备写入数据的函数
	//第一个参数:写入句柄
	//第二个参数:待写入的数据缓冲区
	//第三个参数:待写入数据的字节数
	//第四个参数:实际写入的字节数
	//第五个参数;异步操作的重叠结构(可选)
	DWORD dwWrite;
	if (!WriteFile(m_hWrite, buffer, wcslen(buffer) * 2 + 1, &dwWrite, NULL))
	{
		MessageBox(L"写入数据失败");
		return;
	}

}

子进程读入数据
获取读取句柄和写入句柄

	m_hRead = GetStdHandle(STD_INPUT_HANDLE);
	m_hWrite = GetStdHandle(STD_OUTPUT_HANDLE);
void CSubPipDlg::OnBnClickedBtnRead()
{
	wchar_t buffer[100] = { 0 };
	DWORD dwRead = 0;
	if (!ReadFile(m_hRead, buffer, sizeof(buffer), &dwRead, NULL))
	{
		MessageBox(L"读取数据失败");
		return;
	}

	MessageBox(buffer);
}

请添加图片描述

子进程写入数据父进程读取数据原理一致

命名管道

命名管道服务器在这里插入图片描述
命名管道客户端在这里插入图片描述

服务器命名管道的创建

//命名管道
void CServerDlg::OnBnClickedBtnCreate()
{
	//第一个参数:名字,名字格式:\\.\pipe\pipename
	//第二个参数:打开模式 PIPE_ACCESS_DUPLEX双工模式,FILE_FLAG_OVERLAPPED 在读写过程中会发送一个信号
	//第三个参数:管道模式  PIPE_TYPE_MESSAGE 消息的方式
	//第四个参数:最大实例个数
	//第五个参数:输出的缓冲大小
	//第六个参数:输入的缓冲区大小
	//第七个参数:默认的超时时间
	//第八个参数:安全描述
	m_hPipe=CreateNamedPipe(L"\\\\.\\pipe\\test", PIPE_ACCESS_DUPLEX| FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE,1,1024,1024,0,NULL);

	if (m_hPipe == INVALID_HANDLE_VALUE)
	{
		MessageBox(L"创建命名管道失败");
		return;
	}

	//创建匿名事件对象
	HANDLE hEvent=CreateEvent(NULL, TRUE, FALSE,NULL);


	//异步 I/O 操作的参数和状态信息
	OVERLAPPED ol = {0};
	ol.hEvent = hEvent;

	//等待客户端的链接
	//ConnectNamedPipe 等待客户端有没有连接管道
	if (FALSE == ConnectNamedPipe(m_hPipe, &ol))
	{
		if (GetLastError() != ERROR_IO_PENDING)
		{
			MessageBox(L"等待客户端链接失败");
			return;
		}
	}

	//判断有没有信号
	if (WaitForSingleObject(hEvent, INFINITE) == WAIT_FAILED)
	{
		MessageBox(L"等待对象失败");
		CloseHandle(m_hPipe);
		CloseHandle(hEvent);
		m_hPipe = NULL;
		return;
	}
	CloseHandle(hEvent);
}

客户端管道的连接

void CClientDlg::OnBnClickedBtnConnect()
{
	//判断有没有可以用的管道
	if (FALSE == WaitNamedPipe(L"\\\\.\\pipe\\test", NMPWAIT_WAIT_FOREVER))
	{
		MessageBox(L"当前没有可以利用的命名管道");
		return;
	}

	//打开管道
	//第一个参数:管道名
	//第二个参数:读写模式
	//第三个参数:共享模式 0表示不共享
	//第四个参数:安全属性
	//第五个参数:创建方式
	//第六个参数:文件属性
	//第七个参数:提供文件的拓展属性
	CClientDlg::m_hPipe=CreateFile(L"\\\\.\\pipe\\test", GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
	if (m_hPipe == INVALID_HANDLE_VALUE)
	{
		MessageBox(L"打开管道失败");
		m_hPipe = NULL;
		return;
	}


}

请添加图片描述

邮槽

邮槽是一种基于文件的通信机制,通过创建一个具有唯一名称的邮槽对象,进程可以向该邮槽写入消息,而其他进程可以从该邮槽读取消息。邮槽支持广播方式,即多个进程都可以从同一个邮槽读取相同的消息。需要注意的是,邮槽是单向的,只支持从邮槽中读取消息或者向邮槽写入消息,不能同时进行读写操作。此外,邮槽只能用于同一台计算机上的进程间通信,不能用于跨网络的通信。 邮槽是一种简单而可靠的进程间通信机制,适用于需要在同一台计算机上的多个进程之间传递消息的场景。使用邮槽可以实现进程之间的解耦和异步通信,提高系统的可扩展性和响应性。

邮槽服务器

设置ui
在这里插入图片描述

初始化邮槽

BOOL CMailSlotDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	//创建油槽
	//第一个参数:名字
	//第二个参数:最大消息的最大大小
	//第三个参数:超时时间
	//第四个参数:安全属性
	m_hMailSlot=CreateMailslot(L"\\\\.\\mailslot\\test", 0, MAILSLOT_WAIT_FOREVER, NULL);
	if (m_hMailSlot == INVALID_HANDLE_VALUE)
	{
		MessageBox(L"创建邮槽失败");
		return TRUE;
	}

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

读取内容

//读取
void CMailSlotDlg::OnBnClickedBtnRead()
{
	wchar_t buffer[100] = { 0 };
	DWORD dwRead=0;
	//第一个参数:窗口句柄
	//第二个参数:数据缓存
	//第三个参数:读取的大小
	//第四个参数:实际读了多少
	//第五个参数:溢出量
	if (!ReadFile(m_hMailSlot, buffer, sizeof(buffer), &dwRead, NULL))
	{
		MessageBox(L"读取数据失败");
		return;
	}
	MessageBox(buffer);
}

邮槽客户端

ui设置
在这里插入图片描述

void CMailSlotClientDlg::OnBnClickedBtnWrite()
{
	HANDLE hMainSlot=CreateFile(L"\\\\.\\mailslot\\test", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hMainSlot == INVALID_HANDLE_VALUE)
	{
		MessageBox(L"打开邮槽失败");
		return;
	}

	wchar_t buffer[100] = L"邮槽客户端";
	DWORD dwWrite = 0;
	if (!WriteFile(hMainSlot, buffer, wcslen(buffer) * 2 + 1, &dwWrite, NULL))
	{
		MessageBox(L"写入数据失败");
		return;
	}
}

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/724343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring的事务处理@Trasactional Aop处理第二弹

书接上回 ,我们针对spring中的ApplicationContext类的扩展功能-事件发布和监听处理源码进行了解析,知道了消息是如何存放和传递给监听器处理的。这章我们看下另外一个重量级的组件Transactional事务处理是如何实现的。 我们可能都了解过声明式的事务处理…

十三、弹性容器flex的样式1

目录&#xff1a; 1.基础准备 2.属性解析 一、基础准备 设置ul为弹性元素&#xff0c;默认是flex-direction:row&#xff0c;所以不用设置&#xff0c;然后在让里面的方块不进行伸缩。 我们看到小方块超出了边框 <style>*{margin: 0;padding: 0;list-style: none;}ul{wi…

vant List组件实现上拉加载中 首次进行load事件执行两次的问题

需求&#xff1a; 进行tab切换时&#xff0c;其中一次tab下有上拉加载的功能 问题&#xff1a; 在第一次切换到带有上拉加载列表功能的tab&#xff0c;执行加载list的load事件执行了两次造成数据的重复加载&#xff0c;另外如果这个list的高度全部在可视范围内&#xff0c;首次…

STM32:Custom HID实现USB双向通信

本文章主要讲了使用STM32的USB Device&#xff0c;实现控制板和电脑通信功能。从而实现&#xff0c;上位机对控制板进行调试。 USB Device可以有多种类型&#xff0c;实现双向通信的话&#xff0c;推荐使用Custom HID类型。 首先使用STM32CubeMx实现功能引脚配置并且生成对应…

Win11的两个实用技巧系列之关闭输入法悬浮窗方法、记住窗口位置禁用或启用的方法

Win11输入法悬浮窗怎么去掉? win11关闭输入法悬浮窗方法 Win11输入法悬浮窗怎么去掉&#xff1f;win11安装的输入法有悬浮窗&#xff0c;想要去掉悬浮窗&#xff0c;该怎么操作呢&#xff1f;下面我们就来看看win11关闭输入法悬浮窗方法 很多用户将自己win11更新到了最新版本…

面试题 16.02. 单词频率

设计一个方法&#xff0c;找出任意指定单词在一本书中的出现频率。 你的实现应该支持如下操作&#xff1a; WordsFrequency(book)构造函数&#xff0c;参数为字符串数组构成的一本书get(word)查询指定单词在书中出现的频率 示例&#xff1a; WordsFrequency wordsFrequency …

git cherry-pick 用法

1. 切换到目标分支 说明&#xff1a;本人基于 master 新建分支 master-fxd&#xff0c;那么目标分支为 master-fxd git checkout <target-branch>2. 从其他分支选择并应用单个提交 说明&#xff0c;其他分支例如 dev 提交的代码&#xff0c;使用 jihulab.com 比较 master…

针对WordPress程序无法升级最新版本的问题分析

WordPress程序是当前使用率最高的CMS系统之一&#xff0c;因开发功能完善&#xff0c;WordPress模板和插件众多而著称&#xff0c;茹莱神兽做三个网站&#xff0c;其中有两个网站使用的是WordPress程序搭建&#xff0c;可见它的受欢迎程度。 而WordPress程序本身也相当给力&a…

刷简单的题也很吃力怎么办?(经验分享)

目录 一、前言 1.刷简单的题也很吃力怎么办&#xff1f; 2.不重视这种问题会怎么样&#xff1f; 二、找到属于自己的解决方案 三、根据问题进行分解或建立思维导图​​​​​​​ 四、分享刷题网站 一、前言 1.刷简单的题也很吃力怎么办&#xff1f; 有的时候在当时学完…

ZMQ在windows下配合VS2017使用(c++)

ZMQ专题学习之四&#xff1a;libzmq的发布及订阅方式_jyl_sh的博客-CSDN博客 一、背景介绍 高速并发消息通信框架——ZeroMQ详解&#xff08;一&#xff09; - 知乎 (zhihu.com) zmq将socket进行了封装&#xff0c;可以快速在两个进程间进行通信 二、编译libzip https:/…

超详细Redis入门教程——Redis缓存

前言 本文小新为大家带来 Redis缓存 相关知识&#xff0c;具体内容包括Jedis客户端&#xff08;包括&#xff1a;Jedis简介&#xff0c;创建工程&#xff0c;使用 Jedis 实例&#xff0c;使用 JedisPool&#xff0c;使用 JedisPooled&#xff0c;连接 Sentinel 高可用集群&…

锂电池组冷却模型

文章最下方的长方形小方框内有博主的QQ名片获取本文同款程序 硕博期间所有的程序代码&#xff0c;一共2个多g&#xff0c;可以给你指导&#xff0c;赠送半个小时的语音电话答疑。电池数据辨识程序各种卡尔曼滤波算法都在里面了&#xff0c;后续还会有新模型的更新。快速入门BM…

初识栈溢出 pwn02

题目给了一个链接和端口 pwn.challenge.ctf.show 28183&#xff0c;可以nc看一下 题目给的链接和端口的其实是用来放进我们编写的exp脚本的 还给了一个附件 stack 下载好后拖进kali使用file和checksec命令检查一下 发现是一个32位的程序 No canary found 表示没有金丝雀保…

Stable Diffusion 多角度人设立绘快速生成多种方法

对于插画师构建人物立绘图设计一套多方位的人设可能要很久&#xff0c;但是使用SD进行操作的话就非常简单了&#xff0c;这个利用ControlNet骨骼图进行配置操作。 供一些样图参考&#xff0c;也可以使用ADetailer进行人物相关部位的修复。 文章目录 准备工作关键词绘制使用骨骼…

深入理解ASEMI整流桥KBP210特性及其应用

编辑-Z 在电子工程领域&#xff0c;整流器是一种重要的元件&#xff0c;它能将交流电&#xff08;AC&#xff09;转换为直流电&#xff08;DC&#xff09;。其中&#xff0c;整流桥KBP210是一种常见的整流器&#xff0c;因其优秀的性能和广泛的应用&#xff0c;受到了工程师们…

【专题速递】大模型、带宽优化、智能外呼和AIGC的数据实践

// ChatGPT的爆发为音视频带来了怎样的革新&#xff1f;AIGC又将如何辅助音视频技术为用户带来更好的体验&#xff1f;7月29日LiveVideoStackCon上海站AI与多媒体专场&#xff0c;为您解答。 AI与多媒体 随着生活方式及习惯的变化&#xff0c;人们对于媒体内容与体验有着更高…

8、离线数仓同步数据

1、 用户行为数据同步 1.1、 数据通道 用户行为数据由Flume从Kafka直接同步到HDFS&#xff0c;由于离线数仓采用Hive的分区表按天统计&#xff0c;所以目标路径要包含一层日期。具体数据流向如下图所示。 1.2、 日志消费Flume配置概述 按照规划&#xff0c;该Flume需将Kafka…

案例挑战——事务传播行为

事务的传播行为 一、背景介绍二、 什么是事物的传播行为常见的事物传播行为mandatorysupportsrequiredrequired_newnestednot supportnever 三、为什么要有事务的传播行为&#xff0c;它是为了解决什么问题&#xff1f;四、如何使用事务的传播行为外围方法没有事务&#xff0c;…

audio标签如何去掉controls属性上的下载和倍速

<audioref"audioPlayer":src"data.url"controlstimeupdate"updateProgress" ></audio> controlslist 属性将帮助浏览器选择在媒体元素上显示的控件。 <audioref"audioPlayer":src"data.url"controlscontrol…

【Hello mysql】 数据库表操作

Mysql专栏&#xff1a;Mysql 本篇博客简介&#xff1a;介绍数据库的表操作 数据库表操作 创建表查看表结构修改表添加列修改列删除列修改表名修改列名 删除表总结 创建表 语法 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set…