17 MFC进程通信

文章目录

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

剪切板

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

发送

//设置剪切板数据
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;
	}
}

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序如何进行开发?

文章目录 0.引言1.注册微信公众平台账号2.准备微信开发者工具3.创建微信小程序并预览 0.引言 笔者编程一般编得较多的是桌面软件,有时也会编手机软件,这些软件都必须安装才能使用,这限制了软件的推广。而现有社交软件如微信使用得较广泛&…

Linux的编译器——gcc/g++(预处理、编译、汇编、链接)

文章目录 一.程序实现的两个环境二.gcc如何完成1.预处理2.编译3.汇编4.链接 三.动态库与静态库对比下二者生成的文件大小 四.gcc常用选项 前言: 本文主要认识与学习Linux环境下常用的编译器——gcc(编译C代码)/g(编译C代码&#x…

深度学习--神经网络全面知识点总结(持续更新中)

文章目录 神经网络基础1.1 什么是神经网络?1.2 神经元和激活函数1.3 前向传播和反向传播1.4 损失函数和优化算法 深度神经网络2.1 卷积神经网络(CNN)2.2 循环神经网络(RNN)2.3 长短期记忆网络(LSTM&#xf…

凝思系统docker离线安装

# linux离线安装docker (18.03.1-ce) ## 解压,得到docker文件夹 tar xzvf docker-18.03.1-ce.tgz ## 将docker文件夹里面的所有内容复制到/usr/bin目录 sudo cp docker/* /usr/bin/ ## 开启docker守护进程 sudo dockerd & 当终端中显示【API list…

Mathtype7Mac苹果ios简体中文版

对于很多人来说,每次编辑文字的时候遇到公式简直就是噩梦。像那些复杂的数学、物理还有化学公式,太难编辑出来了。 那么我们该怎么解决这些难题呢?其实很简单,用公式编辑器就行了。 公式编辑器,是一种工具软件&#…

网络安全之反序列化漏洞分析

简介 FastJson 是 alibaba 的一款开源 JSON 解析库,可用于将 Java 对象转换为其 JSON 表示形式,也可以用于将 JSON 字符串转换为等效的 Java 对象分别通过toJSONString和parseObject/parse来实现序列化和反序列化。 使用 对于序列化的方法toJSONStrin…

卷积神经网络| 猫狗系列【AlexNet】

首先,搭建网络: AlexNet神经网络原理图: net代码:【根据网络图来搭建网络,不会的看看相关视频会好理解一些】 import torchfrom torch import nnimport torch.nn.functional as Fclass MyAlexNet(nn.Module): def…

Flutter学习四:Flutter开发基础(六)调试Flutter应用

目录 0 引言 1 Flutter异常捕获 1.1 Dart单线程模型 1.2 Flutter异常捕获 1.2.1 Flutter框架异常捕获 1.2.1.1 Flutter默认异常捕获方式 1.2.1.2 自己捕获异常并上报 1.2.2 其他异常捕获与日志收集 1.2.3 最终的错误上报代码 0 引言 本文是对第二版序 | 《Flutter实…

《Lua程序设计》--学习2

表 Lua语言中的表本质上是一种辅助数组(associative array),这种数组不仅可以使用数值作为索引,也可以使用字符串或其他任意类型的值作为索引(nil除外)。 Lua语言中的表要么是值要么是变量,它…

防火墙基本原理详解

概要 防火墙是可信和不可信网络之间的一道屏障,通常用在LAN和WAN之间。它通常放置在转发路径中,目的是让所有数据包都必须由防火墙检查,然后根据策略来决定是丢弃或允许这些数据包通过。例如: 如上图,LAN有一台主机和一…

【macOS 系列】如何在mac 邮件客户端配置QQ邮箱和第二个账号

文章目录 一、配置QQ邮箱二、添加新的账户 一、配置QQ邮箱 需要在QQ邮箱账户设置中开启: 开启时,会让你发短信到指定号码,然后就会弹出一个验证码 也就是添加邮箱的密码不是QQ密码,而是这个验证码,这个可以生成多个&…

【OpenGL】读取视频并渲染

😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍读取视频并渲染。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路&#…

ELK实验部署过程

ELK集群部署环境准备 配置ELK日志分析系统 192.168.1.51 elk-node1 es、logstash、kibana 192.168.1.52 elk-node2 es、logstash 192.168.1.53 apache logstash (我这里是把虚拟机的配置全部都改为2核3G的) 2台linux 第1台:elk-nod…

【数据库原理】MyShop 商城数据库设计(SQL server)

MyShop 商城数据库设计 项目背景定义课程设计要求概念结构设计逻辑结构设计数据结构的描述用户信息数据结构的描述地址信息数据结构的描述商品类别数据结构的描述商品数据结构的描述购物车数据结构的描述订单数据结构的描述订单项数据结构的描述 物理结构设计用户表结构地址表结…

STM32——GPIO配置

文章目录 一、GPIO八种模式1. 输入2. 输出3. 如何选择GPIO的模式 二、库函数GPIO配置1. 配置代码2.参数设置 一、GPIO八种模式 GPIO的输入输出是对于STM32单片机来说的。以下仅为个人粗略笔记,内部电路分析可参考博客https://blog.csdn.net/k666499436/article/det…

计算机网络_ 1.3 网络核心(数据交换_电路交换_多路复用)

计算机网络_数据交换_电路交换_多路复用 多路复用频分多路复用FDM时分多路复用TDM波分多路复用WDM码分多路复用CDM 多路复用 多路复用(Multiplexing),简称复用,是通信技术的基本概念。 链路/网络资源(如带宽&#x…

【K8S系列】如何高效查看 k8s日志

序言 你只管努力,其他交给时间,时间会证明一切。 文章标记颜色说明: 黄色:重要标题红色:用来标记结论绿色:用来标记一级论点蓝色:用来标记二级论点 Kubernetes (k8s) 是一个容器编排平台&#x…

docker安装失败 应用程序无法启动,因为应用程序的并行配置不正确

问题描述 报错“应用程序无法启动,因为应用程序的并行配置不正确”。 配置:windows10 解决过程 网上的解决方案有三种: 启动windows服务Windows Modules Installer。运行sxstrace.exe。安装visual c相关依赖。下载visual studio installer…

1.6 OSI 七层参考模型

OSI 参考模型 OSI参考模型解释的通信过程OSI参考模型数据封装与通信过程物理层功能数据链路层功能网络层的功能传输层功能会话层功能表示层功能应用层功能 开放系统互连 (OSI)参考模型是由国际标准化组织 (ISO) 于1984年提出的分层网络体系结构模型目的是支持异构网络系统的互联…

Selenium--做任何你想做的事情

大家好,今天为大家介绍Selenium自动化浏览器。就是这样!你可以通过这种力量做任何你想做的事情。 “getDevTools() 方法返回新的 Chrome DevTools 对象,允许您使用 send() 方法发送针对 CDP 的内置 Selenium 命令。这些命令是包装方法&#x…