17 MFC进程通信

news/2024/12/4 16:08:08/

文章目录

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

剪切板

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

发送

//设置剪切板数据
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.ppmy.cn/news/759832.html

相关文章

电脑闪黄灯,屏幕没反应

电脑闪黄灯,屏幕没反应 拔掉电源线,再次启动,恢复正常。

J-LINK放了一晚,不能识别,灯一直闪

J-LINK放了一晚,不能识别,灯一直闪。可是咋天还是好好的。 我的J-LINK是V6.44的固件。 反复插拔上电,发现还是无法下载程序,无法识别。 网上查了一下,是ROM丢失吗?我需要刷一下固件吗? 。。。。…

护眼灯频闪是什么意思?如何消除led灯频闪

人造光源中很多都有频闪现象,比如led护眼灯,其中的缘由大致有两个:一个是电流不稳定导致灯光不规律闪烁,还有一个就是灯具本身的调光系统导致的,即人为地设定一定频率的闪烁。这样做的原因是,低亮环境下小电…

dell电脑换上内存后闪黄灯解决办法

dell电脑换上新内存后不断闪黄灯,规律是2次闪黄灯7闪黄灯。 解决办法: 产生问题主要是由内存导致,可以更换内存方式解决。 比如先插单根内存条,再逐步查找问题。

关于刷小米路由R3G出现 Starting kernel ..不启动黄灯问题,已解决

前段时间为手贱想把路由器固件升一个级,以前也用的是相同的固件,但是这次不知道为什么使用TTL刷机后,出现了Starting Kernel…的情况 一直卡面这里不动,路 由器灯黄灯。在网上查了很多资料都没有得到有效的解决办法,看…

DT7飞控 刷固件 校准 闪黄灯解决方案

1.飞控闪黄灯怎么办 黄灯闪烁是因为遥控器电源指示灯黄灯常亮表示摇杆校准出错。 解决方案:使用rc system调参软件解决 下载地址:https://www.dji.com/cn/downloads/softwares/assistant-dt7-dr16-rc-system 2.飞控如何校准 依然使用上…

小米电脑输入密码后白屏闪烁(小米电脑自动更新后白屏闪烁)

我的最终解决方案为: Ctrl+Alt+Del之后调出关机界面--按住Shift点重启--重启后实际进入了“安全模式”(蓝屏背景) --疑难解答--高级选项--系统还原--根据列表中的更新记录选择还原 参考:小米笔记本win10如何进入安全模式电脑-…

x1电源灯一直闪_343-1advance的STOP灯一直亮黄灯,RUN灯一直闪绿灯,X1P1亮黄灯,通信不上-工业支持中心-西门子中国...

楼主的CP 343-1的SF指示灯没有亮,而且X1P1亮,即表明CP 343-1的的硬件与连线,没有问题。现主要是弄清CPU的SF灯亮的原因,这就需要进行系统的在线诊断。 1、STOP灯一直亮黄灯,RUN灯一直闪绿灯: 表明在启动过程…