little_lamb的个人主页

http://www.qtcn.org/bbs/u/176322  [收藏] [复制]

little_lamb

  • 0

    关注

  • 1

    粉丝

  • 2

    访客

  • 等级:新手上路
  • 总积分:0
  • 保密,2016-10-20

最后登录:2017-07-05

更多资料

日志

进程间通信——管道

2017-05-02 16:16
Windows下用管道通信(pipe)实现进程间数据共享

        管道是一种用于在进程间共享数据的机制,其实质是一段共享内存。Windows系统为这段共享的内存设计采用数据流I/0的方式来访问。由一个进程读、另一个进程写,类似于一个管道两端,因此这种进程间的通信方式称作“管道”。

        管道分为匿名管道和命名管道:
        匿名管道只能在父子进程间进行通信,不能在网络间通信,而且数据传输是单向的,只能一端写,另一端读。
        命令管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时间只能有一端读、一端写。

创建匿名管道:

1. 定义安全属性结构体:    
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle = TRUE;//表示可被子进程所继承
sa.lpSecurityDescriptor = NULL; //安全描述符号一般都设置成NULL,即默认描述符
sa.nLength = sizeof(SECURITY_ATTRIBUTES); //管道长度

其中SECURITY_ATTRIBUTES结构体的定义为:    
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

2. 创建管道:    
BOOL WINAPI CreatePipe(
PHANDLE hReadPipe,//读取端句柄
PHANDLE hWritePipe,//输入端句柄
LPSECURITY_ATTRIBUTES lpPipeAttributes,//安全属性
DWORD nSize// 管道的缓冲区容量,NULL表示默认大小
);

3. 读取管道内数据:  
BOOL ReadFile(
HANDLE hFile,//句柄,可以是标准输入输出流或文件或管道
LPVOID lpBuffer,  //读取的数据写入缓冲区
DWORD nNumberOfBytesToRead,//指定读取的字节数
LPDWORD lpNumberOfBytesRead,//实际读取的字节数
LPOVERLAPPED lpOverlapped//用于异步操作,一般置为NULL
);

4. 向管道内写入数据:    
BOOL WriteFile(
HANDLE hFile,//句柄,同上
LPCVOID lpBuffer,//指定待写入的数据
DWORD nNumberOfBytesToWrite,//写入的数据量
LPDWORDlp NumberOfBytesWritten,//实际要写的数据量
LPOVERLAPPED lpOverlapped//一般置为NULL
);

5. 为实现父子进程间的通信,需要对子进程的管道进行重定向:
我们知道创建子进程函数 CreateProcess中有一个参数STARUIINFO,默认情况下子进程的输入输出管道是标准输入输出流,
可以通过下面的方法实现管道重定向:    
STARTUPINFO si;
si.hStdInput   = hPipeInputRead;   //输入由标准输入 -> 从管道中读取  
si.hStdOutput  = hPipeOutputWrite; //输出由标准输出 -> 输出到管道

创建命名管道:
       命名管道有点类似我们常听见的服务器端和客户端,命名管道有自己的名字。
首先要指定管道名,管道名遵循的格式为:\\.\pipe\pipename。最多可达256个字符的长度,
而且不区分大小写例如:"\\\\.\\pipe\\Name_pipe_demon_get"


1.服务器端创建命名管道
HANDLE WINAPI CreateNamedPipe(
LPCTSTRlpName,//管道名
DWORD dwOpenMode,//管道打开方式
//PIPE_ACCESS_DUPLEX  该管道是双向的,服务器和客户端进程都可以从管道读取或者向管道写入数据
//PIPE_ACCESS_INBOUND 该管道中数据是从客户端流向服务端,即客户端只能写,服务端只能读。
//PIPE_ACCESS_OUTBOUND 该管道中数据是从服务端流向客户端,即客户端只能读,服务端只能写

DWORD dwPipeMode,//管道的模式
//PIPE_TYPE_BYTE   数据作为一个连续的字节数据流写入管道
//PIPE_TYPE_MESSAGE 数据用数据块(名为“消息”或“报文”)的形式写入管道
//PIPE_READMODE_BYTE 数据以单独字节的形式从管道中读出
//PIPE_READMODE_MESSAGE 数据以名为“消息”的数据块形式从管道中读出(要求指定PIPE_TYPE_MESSAGE)
//PIPE_WAIT 同步操作在等待的时候挂起线程

//PIPE_NOWAIT 同步操作立即返回
DWORD nMaxInstances,//表示该管道所能够创建的最大实例数量。必须是1到常数PIPE_UNLIMITED_INSTANCES(255)间的一个值
DWORD nOutBufferSize,//表示管道的输出缓冲区容量,为0表示使用默认大小。
DWORD nInBufferSize,//表示管道的输入缓冲区容量,为0表示使用默认大小。
DWORD nDefaultTimeOut,//表示管道的默认等待超时。
LPSECURITY_ATTRIBUTES lpSecurityAttributes//表示管道的安全属性。
);    

2.创建完成后等待连接        
BOOL WINAPI ConnectNamedPipe(
HANDLE hNamedPipe,//命名管道句柄
LPOVERLAPPED lpOverlapped//一般为NULL
);      

3.服务器端就绪后,客户端开始连接        
BOOL WINAPI WaitNamedPipe(
LPCTSTR lpNamedPipeName,//命名管道名称
DWORD nTimeOut//等待时长
);        

连接成功后,打开管道进行数据通信,使用CreateFile,ReadFile和WriteFile,前面匿名管道已经给出了具体使用方法。


分类:默认分类|回复:0|浏览:720|全站可见|转载
 

Powered by phpwind v8.7 Certificate Copyright Time now is:05-01 23:29
©2005-2016 QTCN开发网 版权所有 Gzip disabled