管道(Pipe)是一种用于进程间共享数据的机制,实质是共享一段内存,windows系统为这段共享内存设计采用数据流I/O的方式访问。由一个读一个写,类似于一个管道两端。
管道分为命名管道和匿名管道。
匿名管道只能在父子进程间进行通信,不能在网络间通信,而数据传输是单向的。
命名管道可以在任意进程间通信,通信是双向的。
创建命名管道 CreateNamedPipe
HANDLE WINAPI CreateNamedPipe(
LPCTSTR lpName, // 管道名称, 命名方式:\\ServerName\pipe\PipeName 或者 \\.\pipe\PipName
DWORD dwOpenMode, // 打开模式
DWORD dwPipMode, // 管道模式(管道类型模式、管道读写模式、管道等待模式)
DWORD nMaxInstances, //pipe所能建立的最多实例
DWORD nOutBufferSize, //输入缓存大小
DWORD nInBufferSize, //输出缓存大小
DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES lpSecurity_attributes
);
服务端等待客户端连接的函数ConnectNamedPipe
BOOL WINAPI ConnectNamedPipd(
HANDLE hNamedPipe,
LPOVERLAPPED lpOverlapped //指向OVERLAPPED结构的指针
);
管道关闭DisconnectNamedPipe
等待状态改变WaitNamedPipe
客户端使用CreateFile打开管道
pipe读写使用 ReadFile 和 WriteFile
例子:(服务端C++ 客户端Delphi)
服务端(部分代码):
/* 创建命名管道 */
void severpipe::CreateAndConnectInstance()
{
m_hpipe=CreateNamedPipe(m_lpszpipename,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE ,
PIPE_UNLIMITED_INSTANCES,
BUFSIZ*sizeof(TCHAR),
BUFSIZ*sizeof(TCHAR), 1000, NULL );
if (INVALID_HANDLE_VALUE==m_hpipe)
{
std::cerr<<GetLastError()<<std::endl;
}
}
/* 建立连接 */
void severpipe::ConnectToNewClient()
{
BOOL fConnected = FALSE;
fConnected=ConnectNamedPipe(m_hpipe, &oConnect);
if (!fConnected)
{
if (ERROR_IO_PENDING!=GetLastError())
{
std::cout<<"connect failed"<<std::endl;
}
}
}
/* 读取函数 返回读取内容 */
char* severpipe::PipeReadStr()
{
char* preadbuf = new char[5];
DWORD dwRead;
memset(preadbuf, 0, 5);
if (!ReadFile(m_hpipe, preadbuf, 5, &dwRead, NULL))
{
std::cout<<"read failed"<<std::endl;
}
return preadbuf;
}
客户端(部分代码):
if(WaitNamedPipe(pipename, NMPWAIT_WAIT_FOREVER)=False) then
begin
mmo.Lines.Add('pipe do not exist');
Exit;
end;
//const pipename = '\\.\pipe\samplenamedpipe';
hpipe := createfile(PChar(pipename), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0);
if hpipe=INVALID_HANDLE_VALUE then
begin
mmo.Lines.Add('can not open pipe');
Exit;
end;
if( WriteFile(hpipe, PChar(str)^, Length(str),written,nil)=False) then // str:= 'test';
begin
mmo.Lines.Add('wirte failed');
Exit;
end;
PS:仅供参考, 需要考虑同步问题,可以使用WaitForSingleObject