进程通信

来源:互联网 发布:mac win7 0x80070570 编辑:程序博客网 时间:2024/06/02 16:47

一、进程通信有几种方法:

1.通过剪贴板

2.使用匿名管道

3.命名管道

4.邮槽

二、实现

1.剪贴板:

COleDataSource::SetClipboard()

COleDataSource::GetClipboardOwner()

COleDataSource::Empty()

GlobalAlloc();

GlobalLock();

GlobalUnlock()

..........以上API函数即可,代码略


2.匿名管道:(部分代码如下)



void CMyView::OnCreate() 
{
    SECURITY_ATTRIBUTES sa;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=NULL;


int err=CreatePipe(&hRead,&hWrite,&sa,0);
if(err==0)
{
MessageBox("Create Pipe Error !");
return ;
}
 
STARTUPINFO si;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb=sizeof(STARTUPINFO);
si.dwFlags=STARTF_USESTDHANDLES;
si.hStdInput=hRead;
si.hStdOutput=hWrite;
si.hStdError=GetStdHandle(STD_ERROR_HANDLE);


PROCESS_INFORMATION pi;


if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,
NULL,NULL,TRUE,0,NULL,NULL,&si,&pi))
{
CloseHandle(hRead);
CloseHandle(hWrite);
hRead=NULL;
hWrite=NULL;
MessageBox("创建子进程失败 !");
return ;
}
else
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}






void CMyView::OnWrite() 
{
char buf[]="Hello ! 我是父进程!";
    DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("Write Error !");
return ;
}

}


void CMyView::OnRead() 
{
    char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox("Read Error !");
return ;
}
MessageBox(buf);


}


3.命名管道

命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信。

n将命名管道作为一种网络编程方案时,它实际上建立了一个客户机/服务器通信体系,并在其中可靠地传输数据。
n命名管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统(Named Pipe File System,NPFS)”接口,因此,客户机和服务器可利用标准的Win32文件系统函数(例如:ReadFile和WriteFile)来进行数据的收发。
n命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。而客户机只能同一个现成的命名管道服务器建立连接。
n命名管道服务器只能在WindowsNT或Windows 2000上创建,所以,我们无法在两台Windows95或Windows 98计算机之间利用管道进行通信。不过,客户机可以是Windows 95或Windows 98计算机,与WindowsNT或Windows 2000计算机进行连接通信。
n命名管道提供了两种基本通信模式:字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式,在客户机和服务器之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位,进行数据的收发,每次在管道上发出了一条消息后,它必须作为一条完整的消息读入。


服务器端:
void CNamePipeView::OnWrite() 
{


char buf[]="Hello ! 我是父进程!";
    DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("Write Error !");
return ;
}
}


void CNamePipeView::OnRead() 
{


char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
MessageBox("Read Error !");
return ;
}
MessageBox(buf);


}


void CNamePipeView::OnCreate() 
{
hPipe=CreateNamedPipe("\\\\.\\pipe\\MyPipe",PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
0,1,1024,1024,0,NULL);
if(hPipe==INVALID_HANDLE_VALUE)
{
MessageBox("Create Pipe Error !");
hPipe=NULL;
return ;
}


HANDLE hEvent;
    hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(!hEvent)
{
MessageBox("Create Event Error !");
CloseHandle(hEvent);
hEvent=NULL;
}
    
OVERLAPPED ovalap;
ZeroMemory(&ovalap,sizeof(OVERLAPPED));
ovalap.hEvent=hEvent;


if(!ConnectNamedPipe(hPipe,&ovalap))
{
if(ERROR_IO_PENDING!=GetLastError())
{
MessageBox("等待客户端连接失败! ");
CloseHandle(hEvent);
CloseHandle(hPipe);
hPipe=NULL;
return ;
}
}


if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))
{
MessageBox("等待对象失败 !");
CloseHandle(hEvent);
CloseHandle(hPipe);
hPipe=NULL;
return ;
}
CloseHandle(hEvent);


}


客户端:

void CNameedPipeClientView::OnConnect() 
{


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 CNameedPipeClientView::OnRead() 
{


char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
MessageBox("Read Error !");
return ;
}
MessageBox(buf);

}


void CNameedPipeClientView::OnWrite() 
{
char buf[]="Hello ! 我是子进程!";
    DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("Write Error !");
return ;
}
}

4.邮槽

服务器端:

void CMailSlotView::OnRecv() 
{
   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("Read Error !");
CloseHandle(hMailSlot);
return ;
}
MessageBox(buf);
CloseHandle(hMailSlot);
   
}

客户端:

void CMaiSlot_ClientView::OnSend() 
{
   HANDLE hMailSlot;
   hMailSlot=CreateFile("\\\\.\\mailslot\\MyMailSlot",
  GENERIC_WRITE,FILE_SHARE_READ,NULL,
  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
   if(INVALID_HANDLE_VALUE==hMailSlot)
   {
  MessageBox("打开油槽失败!");
  CloseHandle(hMailSlot);
  return ;
   }
   char buf[]="Hello ! 油槽发送数据!";
   DWORD dwWrite;
   if(!WriteFile(hMailSlot,buf,strlen(buf)+1,&dwWrite,NULL))
   {
  MessageBox("Write Error !");
  CloseHandle(hMailSlot);
  return ;
   }
   CloseHandle(hMailSlot);
}


原创粉丝点击