大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
windows下进程间通信方式:
1、剪贴板(Ctrl+C;Ctrl+V) 2、匿名管道 3、命名管道 4、邮槽
/****************************************************************************************/
一、剪贴板:
void CClipboardDlg::OnBtnSend() //向剪贴板中放置数据
{
if(OpenClipboard()) //打开剪贴板,若打开就独占
{
CString str;
HANDLE hClip;
char *pBuf;
EmptyClipboard();//清空剪贴板并让当前窗口成为剪贴板的拥有者
GetDlgItemText(IDC_EDIT_SEND,str);//获取编辑框文本
hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);//从堆上分配指定数目的字节
pBuf=(char*)GlobalLock(hClip); //锁定内存对象,维护一个锁计数加一,不可移动除非设置GlobalReAlloc
strcpy(pBuf,str);
GlobalUnlock(hClip);//解锁内存对象,GlobalUnlock将锁计数减一
SetClipboardData(CF_TEXT,hClip);//以指定的剪贴板格式向剪贴板中放置数据
CloseClipboard(); //关闭剪贴板
}
}
void CClipboardDlg::OnBtnRecv() //从剪贴板中获取数据
{
if(OpenClipboard())
{
if(IsClipboardFormatAvailable(CF_TEXT))
{
HANDLE hClip;
char *pBuf;
hClip=GetClipboardData(CF_TEXT); //获取剪贴板数据
pBuf=(char*)GlobalLock(hClip);
GlobalUnlock(hClip);
SetDlgItemText(IDC_EDIT_RECV,pBuf);
CloseClipboard();
}
}
}
/****************************************************************************************/
二、匿名管道(CreatePipe):
//匿名管道只能在本地机器上、在父子进程中通信,且子进程必须由父进程启动
1、父进程中:
//构造析构中
hRead = NULL;hWrite = NULL;
if(hRead) CloseHandle(hRead);
if(hWrite) CloseHandle(hWrite);
void CParentView::OnPipeCreate() //创建匿名管道,创建子进程
{
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE; //可以被一个新的进程继承其读写句柄
sa.lpSecurityDescriptor=NULL;//默认的安全描述符
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0)) //创建匿名管道
{
MessageBox(“创建匿名管道失败!”);
return;
}
STARTUPINFO sui; //这个结构体成员真TM的多
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO)); //将结构体中的所有成员置0
sui.cb=sizeof(STARTUPINFO); //结构体大小
sui.dwFlags=STARTF_USESTDHANDLES; //使用标准句柄
sui.hStdInput=hRead; //子进程的标准输入句柄设为管道的读取句柄
sui.hStdOutput=hWrite; //子进程的标准输出句柄设为管道的写入句柄
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE); //得到父进程的标准错误句柄
if(!CreateProcess(“..\\Child\\Debug\\Child.exe”,NULL,NULL,NULL,
TRUE,0,NULL,NULL,&sui,&pi)) //创建一个子进程
{
CloseHandle(hRead); //关闭管道读取句柄
CloseHandle(hWrite); //关闭管道写入句柄
hRead=NULL; //置为NULL,析构就不必执行了
hWrite=NULL;
MessageBox(“创建子进程失败!”);
return;
}
else
{
CloseHandle(pi.hProcess);//在不需要使用内核对象句柄时关闭句柄,引用计数变为1
CloseHandle(pi.hThread);//切记,勿忘!
}
}
void CParentView::OnPipeRead() //从管道中读数据
{
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL)) //可从文件管道控制台读数据
{
MessageBox(“读取数据失败!”);
return;
}
MessageBox(buf);
}
void CParentView::OnPipeWrite() //向管道中写数据
{
char buf[]=”这是父进程通过管道发送的数据:\nhttp://weibo.com/231237992/home”;
DWORD dwWrite; //实际写入的字节数
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox(“写入数据失败!”);
return;
}
}
2、子进程中://添加到当前项目,且和父进程在同一目录下
//构造析构同父进程
void CChildView::OnInitialUpdate() //窗口完全创建成功后第一个调用的函数
{
CView::OnInitialUpdate();
//获取子进程的标准输入和标准输出句柄,即得到管道的读取和写入句柄
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
void CChildView::OnPipeRead()
{
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox(“读取数据失败!”);
return;
}
MessageBox(buf);
}
void CChildView::OnPipeWrite()
{
char buf[]=”这是子进程通过管道写入的数据”;
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox(“写入数据失败!”);
return;
}
}
/****************************************************************************************/
三、命名管道(CreateNamedPipe):
//若要创建命名管道的多个实例,就要多次调用CreateNamedPipe;
//命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节,充分利用了WinNT和Win2000的安全机制。
//将命名管道作为一种网络编程方案时,它实际上建立了一个客户机/服务器通信体系,并可靠传输数据
可以指定哪一组用户可以访问管道,哪一组不可访问,就不需编写用户身份验证的代码了;若用socket,需编码实现
命名管道服务器和客户机的区别:1、服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。
而客户机只能同一个现成的命名管道服务器建立连接。2、命名管道服务器只能在NT或2000上创建,客户机不然。
命名管道提供了两种基本通信模式:字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式在客户机和服务器
之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位进行数据的收发,每次在管道上发出一条消息后,
它必须作为一条完整的消息读入。
1、服务器端:
void CNamedPipeSrvView::OnPipeCreate()
{
//.表示本地机器(远程服务器的名字),固定格式,MYPipe:自定义的管道名
//管道是双向的|重叠模式(读写执行要花一段时间才能完成的函数会立刻返回,耗费时间的操作在后台执行)
//eg:可同时在一个管道句柄上进行读取和写入操作
//参数0:字节模式;此参数决定是字节模式还是消息模式
//参数1:可创建的最大实例数(若想同时连接5个,需调用五次CreateNamedPipe)
//输入输出缓冲区的buffer大小,缺省的超时值,安全属性
hPipe=CreateNamedPipe(“\\\\.\\pipe\\MyPipe”,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
0,1,1024,1024,0,NULL); //创建命名管道
if(INVALID_HANDLE_VALUE==hPipe) //注意返回值
{
MessageBox(“创建命名管道失败!”);
hPipe=NULL;
return;
}
HANDLE hEvent;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); //创建人工重置的事件对象
if(!hEvent)
{
MessageBox(“创建事件对象失败!”);
CloseHandle(hPipe);
hPipe=NULL;
return;
}
OVERLAPPED ovlap;
//若创建命名管道用了FILE_FLAG_OVERLAPPED,必须指定此结构体,包含一个人工重置的事件对象句柄
ZeroMemory(&ovlap,sizeof(OVERLAPPED)); //将此结构体清零
ovlap.hEvent=hEvent; //只需要使用此数据成员
if(!ConnectNamedPipe(hPipe,&ovlap)) //等待客户端连接命名管道
{
if(ERROR_IO_PENDING!=GetLastError())
{
MessageBox(“等待客户端连接失败!”);
CloseHandle(hPipe);
CloseHandle(hEvent);
hPipe=NULL;
return;
}
}
if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE)) //等待事件对象变为有信号状态
{
MessageBox(“等待对象失败!”);
CloseHandle(hPipe);
CloseHandle(hEvent);
hPipe=NULL;
return;
}
CloseHandle(hEvent); //已经有一个客户端连接到命名管道的实例上
}
void CNamedPipeSrvView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
MessageBox(“读取数据失败!”);
return;
}
MessageBox(buf);
}
void CNamedPipeSrvView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]=”既然选择远方,便只顾风雨兼程”;
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox(“写入数据失败!”);
return;
}
}
2、客户端:
//首先构造析构:…
void CNamedPipeCltView::OnPipeConnect()
{
if(!WaitNamedPipe(“\\\\.\\pipe\\MyPipe”,NMPWAIT_WAIT_FOREVER)) //等待命名管道
{
MessageBox(“当前没有可利用的命名管道实例!”);
return;
}
hPipe=CreateFile(“\\\\.\\pipe\\MyPipe”,GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //打开命名管道
if(INVALID_HANDLE_VALUE==hPipe) //注意返回值
{
MessageBox(“打开命名管道失败!”);
hPipe=NULL;
return;
}
}
void CNamedPipeCltView::OnPipeRead()
{
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
MessageBox(“读取数据失败!”);
return;
}
MessageBox(buf);
}
void CNamedPipeCltView::OnPipeWrite()
{
char buf[]=”命名管道测试程序”;
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox(“写入数据失败!”);
return;
}
}
/****************************************************************************************/
四、邮槽(CreateMailslot):
//邮槽是基于广播通信体系设计出来的,采用无连接的不可靠的数据传输。
//油槽是一种单向通信机制,创建邮槽的服务器进程读取数据,打开邮槽的客户机进程写入数据。
//为保证邮槽能在各种win平台下正常工作,传输信息时,应将消息长度限制在424字节以下。
//服务器进程:
void CMailslotSrvView::OnMailslotRecv()
{
HANDLE hMailslot;
hMailslot=CreateMailslot(“\\\\.\\mailslot\\MyMailslot”,0, //0表示消息可为任意大小
MAILSLOT_WAIT_FOREVER,NULL);
if(INVALID_HANDLE_VALUE==hMailslot) //注意返回值(创建命名管道/创建文件)
{
MessageBox(“创建油槽失败!”);
return;
}
char buf[100];
DWORD dwRead;
if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))
{
MessageBox(“读取数据失败!”);
CloseHandle(hMailslot); //关闭邮槽句柄
return;
}
MessageBox(buf);
CloseHandle(hMailslot);//关闭邮槽句柄
}
//客户机进程:
void CMailslotCltView::OnMailslotSend()
{
HANDLE hMailslot;
hMailslot=CreateFile(“\\\\.\\mailslot\\MyMailslot”,GENERIC_WRITE,
FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //打开邮槽文件
if(INVALID_HANDLE_VALUE==hMailslot)
{
MessageBox(“打开油槽失败!”);
return;
}
char buf[]=”I love you.”;
DWORD dwWrite;
if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL)) //向邮槽写数据
{
MessageBox(“写入数据失败!”);
CloseHandle(hMailslot);
return;
}
CloseHandle(hMailslot);
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/183078.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...