邮槽:只允许从客户端发送到服务器,没有可靠性保证,根据广播通信体系所设计,使用邮槽可以建立不可靠的单向数据传输。其优点就是可以很方便的向一个或者多个服务器广播消息
管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。命名管道(Named Pipes)是在管道服务器和一台或多台管道客户机之间进行单向或双向通信的一种命名的管道。一个命名管道的所有实例共享同一个管道名,但是每一个实例均拥有独立的缓存与句柄,并且为客户——服务通信提供有一个分离的管道。实例的使用保证了多个管道客户能够在同一时间使用同一个命名管道。
消息管道(Message Pipe)
用于设置应用程序间的一条永久通讯通道,通过该通道可以象自己的应用程序访问一个平面文件一样读写数据。
匿名管道(Anonymous Pipes)
单向流动,并且只能够在同一电脑上的各个进程之间流动。
命名管道(Named Pipes)
双向,跨网络,任何进程都可以轻易的抓住,放进管道的数据有固定的格式,而使用ReadFile()只能读取该大小的倍数。
可以被使用于I/O Completion Ports
相同点:
1、 都是进程间的通信
2、 都是在重命名机制的基础上实现的()
3、 都采用通用命名规则UNC(Universal Naming Convention)
4、 支持多客户端链接???
不同点:
1、 邮槽是单向通信,服务器只读,客户端只写,不支持重叠IO模式
2、 命名管道,可以是双向通信,可以采用重叠IO模式
邮槽的实现:
服务端:
1) 用CreateMailslot API函数创建一个邮槽句柄。
2) 调用ReadFile API函数,并使用现成的邮槽句柄,从任何客户机接收数据。
客户端:
1) 使用CreateFile这个API函数,针对想向其传送数据的邮槽,打开指向它的一个引用句
柄。
柄。
2) 调用WriteFile这个API函数,向邮槽写入数据。
命名管道的实现:
服务端:
1) 使用API函数CreateNamedPipe,创建一个命名管道实例句柄。
2) 使用API函数ConnectNamedPipe,在命名管道实例上监听客户机连接请求。
3) 分别使用ReadFile和WriteFile这两个API函数,从客户机接收数据,或将数据发给客户
机。
4) 使用API函数DisconnectNamedPipe,关闭命名管道连接。
5) 使用API函数CloseHandle,关闭命名管道实例句柄。
2) 使用API函数ConnectNamedPipe,在命名管道实例上监听客户机连接请求。
3) 分别使用ReadFile和WriteFile这两个API函数,从客户机接收数据,或将数据发给客户
机。
4) 使用API函数DisconnectNamedPipe,关闭命名管道连接。
5) 使用API函数CloseHandle,关闭命名管道实例句柄。
客户端:
1) 用API函数WaitNamedPipe,等候一个命名管道实例可供自己使用。
2) 用API函数CreateFile,建立与命名管道的连接。
3) 用API函数WriteFile和ReadFile,分别向服务器发送数据,或从中接收数据。
4) 用API函数CloseHandle,关闭打开的命名管道会话。
2) 用API函数CreateFile,建立与命名管道的连接。
3) 用API函数WriteFile和ReadFile,分别向服务器发送数据,或从中接收数据。
4) 用API函数CloseHandle,关闭打开的命名管道会话。
命名管道的代码实现:
服务端:
view plaincopy to clipboardprint?
// PipeServer.cpp : Defines the entry point for the console application.
// 管道通信服务器
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define NUM_PIPES 5
#define BUFFER_SIZE 256
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwTransferred;
HANDLE hPipe[NUM_PIPES];
char szBuffer[NUM_PIPES][BUFFER_SIZE];
OVERLAPPED Ovlap[NUM_PIPES];
HANDLE hEvent[NUM_PIPES];
DWORD dwTime = 1000;
BOOL bRead[NUM_PIPES];
for ( int i = 0; i < NUM_PIPES; i++ )
{
// create pipe
if ( (hPipe[i] = CreateNamedPipe("\\\\.\\pipe\\socket_pipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
NUM_PIPES,
0,
0,
dwTime,
NULL)) == INVALID_HANDLE_VALUE )
{
printf("Create Pipe Error: %d\n", GetLastError());
return -1;
}
// Create Event
if ( (hEvent[i] = CreateEvent( NULL, TRUE, FALSE, NULL ) ) == NULL )
{
printf("Create Event Error: %d\n", GetLastError());
continue;
}
bRead[i] = FALSE;
// Init OVERLAPPED
ZeroMemory( &Ovlap[i], sizeof(OVERLAPPED) );
Ovlap[i].hEvent = hEvent[i];
// disconnect pipe
if ( DisconnectNamedPipe( hPipe[i] ) == 0 )
{
printf("DisconnectNamedPipe Error: %d\n", GetLastError());
return -1;
}
// connect pipe
if ( ConnectNamedPipe( hPipe[i], &Ovlap[i] ) == 0 )
{
if ( GetLastError() != ERROR_IO_PENDING )
{
printf("Connect Name Pipe Error: %d\n", GetLastError());
CloseHandle(hPipe[i]);
return -1;
}
}
}
printf("---------------------Server Is Start---------------------\n");
DWORD dwRet, dwPipe;
while ( 1 )
{
// waiting for Event
if ( (dwRet = WaitForMultipleObjects( NUM_PIPES, hEvent, FALSE, INFINITE ))
== WAIT_FAILED)
{
printf("Wait For MultipleObject Error: %d\n", GetLastError());
return -1;
}
dwPipe = dwRet - WAIT_OBJECT_0;
ResetEvent( hEvent[dwPipe] );
// Get Info
if ( GetOverlappedResult( hPipe[dwPipe], &Ovlap[dwPipe], &dwTransferred, TRUE ) == 0 )
{
printf("GetOverlappedResult Error: %d\n", GetLastError());
if ( DisconnectNamedPipe( hPipe[dwPipe] ) == 0 )
{
printf("DisconnectNamedPipe Error: %d\n", GetLastError());
return -1;
}
// Connect again
if ( ConnectNamedPipe( hPipe[dwPipe], &Ovlap[dwPipe] ) == 0 )
{
printf("DisconnectNamedPipe Error: %d\n", GetLastError());
return -1;
}
bRead[dwPipe] = FALSE;
}
else
{
if ( bRead[dwPipe] == FALSE )
{
ZeroMemory( &Ovlap[dwPipe], sizeof(OVERLAPPED) );
Ovlap[dwPipe].hEvent = hEvent[dwPipe];
if ( ReadFile( hPipe[dwPipe], szBuffer[dwPipe],
BUFFER_SIZE, NULL, &Ovlap[dwPipe] )
== 0 )
{
if ( GetLastError() != ERROR_IO_PENDING )
{
printf("ReadFile Error: %d\n", GetLastError());
return -1;
}
}
bRead[dwPipe] = TRUE;
}
else
{
printf("Recevied %d Bytes", dwTransferred);
ZeroMemory( &Ovlap[dwPipe], sizeof(OVERLAPPED) );
Ovlap[dwPipe].hEvent = hEvent[dwPipe];
if ( WriteFile( hPipe[dwPipe], szBuffer[dwPipe], dwTransferred, NULL, &Ovlap[dwPipe] ) == 0 )
{
if ( GetLastError() != ERROR_IO_PENDING )
{
printf("ReadFile Error: %d\n", GetLastError());
return -1;
}
}
bRead[dwPipe] = FALSE;
}
}
}
for ( int i = 0; i < NUM_PIPES; i++ )
{
CloseHandle(hPipe[i]);
}
system("pause");
return 0;
}
客户端:
view plaincopy to clipboardprint?
// PipeClient.cpp : Defines the entry point for the console application.
// 管道通信客服端
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define BUFFER_SIZE 256
#define PIPE "\\\\.\\pipe\\socket_pipe"
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hPipe;
DWORD dwWrite;
// waiting
if ( WaitNamedPipe( PIPE, NMPWAIT_WAIT_FOREVER ) == FALSE )
{
printf("WaitNamedPipe Error: %d\n", GetLastError());
return -1;
}
// create pipe
if ( (hPipe = CreateFile( PIPE, GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL) ) == INVALID_HANDLE_VALUE)
{
printf("CreateFile Error: %d\n", GetLastError());
return -1;
}
// send
if ( WriteFile( hPipe, "This is Test Pipe", 17, &dwWrite, NULL ) == 0 )
{
printf("CreateFile Error: %d\n", GetLastError());
CloseHandle( hPipe );
return -1;
}
DWORD dwRead;
char szBuffer[BUFFER_SIZE];
if ( ReadFile( hPipe, szBuffer, BUFFER_SIZE, &dwRead, NULL ) == 0 )
{
if ( GetLastError() != ERROR_IO_PENDING )
{
printf("ReadFile Error: %d\n", GetLastError());
return -1;
}
}
szBuffer[dwRead] = '\0';
printf("%s", szBuffer);
system("pause");
// recv
return 0;
}