孙鑫: 第十七讲 进程间通信四种方式

 详细讲解进程间通讯的四种方式:剪贴板、匿名管道、命名管道和邮槽。
    并比较分析这几种进程间通信的优点和缺点。
比较:
    剪贴板和匿名管道只能在本机进程间通讯;
    命名管道和邮槽都可以网络进程通讯;
    命名管道只能是点对点的通讯;
    邮槽可以一对多的单向通讯,但是数据量小;
1.剪贴板
void CClipboardDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
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);
    strcpy(pBuf,str);
    GlobalUnlock(hClip);
    SetClipboardData(CF_TEXT,hClip);
    CloseClipboard();
}
}

void CClipboardDlg::OnBtnRecv()
{
// TODO: Add your control notification handler code here
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();
   }
}
}
2.利用匿名管道
父进程:
在view的里添加2个成员变量hRead,hWrite;初始化,在析构函数里判断,如果不为NUILL,就析构
void CParentView::OnPipeCreate()
{
// TODO: Add your command handler code here
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
   MessageBox("创建匿名管道失败!");
   return;
}
STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO));
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;
   hWrite=NULL;
   MessageBox("创建子进程失败!");
   return;
}
else
{
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
}
}

void CParentView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CParentView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="
http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}
子进程:
void CChildView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CChildView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="匿名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}

void CChildView::OnInitialUpdate()
{
CView::OnInitialUpdate();

// TODO: Add your specialized code here and/or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
注意:必须要父进程启动子进程才具有父子关系
3.命名管道(可以跨网络实现进程间的通信)
2种基本通信模式:字节模式和消息模式
服务器:
在view类里添加HANDLE hPipe;初始化;析构
void CNamedPipeSrvView::OnPipeCreate()
{
// TODO: Add your command handler code here
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;
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[]="
http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}
客户端:
void CNamedPipeCltView::OnPipeConnect()
{
// TODO: Add your command handler code here
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()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CNamedPipeCltView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="命名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}
4.邮槽(无连接,不可靠,单向;广播(实现一对多的通信);创建邮槽的服务器读取数据,客户端写入数据)
服务端:
void CMailslotSrvView::OnMailslotRecv()
{
// TODO: Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateMailslot("
\\\\.\\mailslot\\MyMailslot",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()
{
// TODO: Add your command handler code here
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[]="
http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   CloseHandle(hMailslot);
   return;
}
CloseHandle(hMailslot);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
孙鑫.java web开发详解: xml xslt servlet jsp深入剖析与实例应用》是一本介绍Java Web开发技术的书籍。本书以XML、XSLT、Servlet和JSP为核心内容,旨在帮助读者全面了解并深入理解这些技术的应用和原理。 首先,书中详细介绍了XML(可扩展标记语言)的基本语法和应用场景。XML是一种用于存储和传输数据的标记语言,具有结构清晰、易于扩展和可读性好的特点。本书通过实例演示了XML的使用方法,包括如何创建、解析和操作XML文档。同时,还介绍了XML的相关技术和工具,如DTD(文档类型定义)、Schema(模式)、XPath(路径语言)和XSLT(可扩展样式表语言转换)。 接着,书中系统地介绍了Servlet和JSP的应用和原理。Servlet是Java编写的服务器端程序,用于响应客户端的请求并生成动态内容。JSP(Java Server Pages)是一种将Java代码嵌入到HTML中的技术,用于生成动态网页。本书通过实例展示了如何使用Servlet和JSP开发Web应用,包括处理请求和响应、会话管理、数据库访问等方面的内容。 最后,本书还深入剖析了XML、XSLT、Servlet和JSP的底层原理,包括HTTP协议、请求和响应的处理流程、Web容器的工作原理等。通过深入理解这些原理,读者能够更好地进行Web应用的开发和调优。 总之,《孙鑫.java web开发详解: xml xslt servlet jsp深入剖析与实例应用》是一本全面介绍Java Web开发技术的书籍,通过详细的实例和剖析,帮助读者掌握XML、XSLT、Servlet和JSP的应用和原理,提升Web开发的技能和水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值