windows学习历程-IPC之命名管道

                                                                                                                                命名管道
命名管道数据传输过程:在服务器端调用CreateNamedpipe创建命名管道之后,调用ConnectNamedpipe函数让服务器端进程等待客户端进程连接到该命名管道的实例上。
在客户端首先调用WaiteNamedpipe函数判断当前是否有可以利用的命名管道实例,如果有,就调用CreateFile函数打开该命名管道的实例,并且建立一个连接。
下面是一些函数,以及一个具体实例。
一、服务器端会调用以下函数:
(1)创建命名管道函数CreateNamedPipe
原型  HANDLE CreateNamedPipe(
  LPCTSTR lpName, // 指向管道名称的指针
  DWORD dwOpenMode, // 管道打开模式
  DWORD dwPipeMode, // 管道模式
  DWORD nMaxInstances, // 最大实例数
  DWORD nOutBufferSize, // 输出缓存大小
  DWORD nInBufferSize, // 输入缓存大小
  DWORD nDefaultTimeOut, // 超时设置
  LPSECURITY_ATTRIBUTES lpSecurityAttributes // 安全属性指针
);
     (2) 在命名管道实例上监听客户机连接请求的函数ConnectNamedPipe
原型:ConnectNamedPipe(
            HANDLE hNamedPipe,
            LPOVERLAPPED lpOverlapped
    );
参数含义:
         hNamedPipe:管道的句柄
         lpOverlapped ,如果设为NULL(传递ByVal As Long),表示将线程挂起,直到一个客户端同管道连接为止。
否则就立即返回;此时,如果管道尚未连接,客户同管道连接时就会触发lpOverlapped结构中的事件对象。随后,可用一个等待函数来监视连接
      (3)从客户机接收数据函数ReadFile:         
原型:BOOL ReadFile(
HANDLE hFile, //文件的句柄
LPVOID lpBuffer, //用于保存读入数据的一个缓冲区
DWORD nNumberOfBytesToRead, //要读入的字节数
LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针
LPOVERLAPPED lpOverlapped //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须用这个参数引用一个特殊的结构。该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
 );
      (4)关闭命名管道实例句柄函数CloseHandle:
CloseHandle(
    __in HANDLE hObject   //代表一个已打开对象句柄
    ); 
     (5)memset函数
 void *memset(void *s, int ch, size_t n);函数解释:将s中前n个字节替换为ch并返回s
  memset功能:是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。
服务器端代码:
#include <stdio.h>
#include <Windows.h>
#define PIPENAME0 "//./Pipe/Test"  
#define MAXDATANUM 1024
int main()
{
DWORD ReadNum = 0;   //DWORD 表示32位字节无符号整数这里定义了服务器读入的字节数ReadNum初始为0   Windows下经常用来保存地址(或者存放指针) 
char buffer[MAXDATANUM]; //定义一个char类型的数组存放读取的数据
HANDLE g_hPipe = INVALID_HANDLE_VALUE; //HANDLE是专门定义句柄的标示符 定义了一个名为g_hPipe的句柄为无效句柄值
printf("Server of name pipe is testing..........\n"); //创建名称为Test的命名管道
g_hPipe = CreateNamedPipe(PIPENAME0,PIPE_ACCESS_DUPLEX,PIPE_READMODE_BYTE,2,0,0,1000,NULL); //创建 命名管道返回g_hPipe管道句柄
// 参数1 PIPENAME0 表示管道的名称   参数2 PIPE_ACCESS_DUPLEX 表示管道创建好后的打开模式即标志以双向传输方式打开一个管道(双工通信)

//参数3 PIPE_READMODE_BYTE 命名管道提供以字节方式通信 参数4 “2”表示管道内的最大实例数 参数“0”,“0”,“1000”,“NULL”分别表示输出缓存大小、输入缓存大小、超时设置、安全属性的指针 


//判断句柄是否有效如果无效调用CloseHandle函数关闭句柄

if (INVALID_HANDLE_VALUE == g_hPipe)
{
printf("Create name pipe is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}

printf("Waiting connect......\n");

//判断客户端与管道是否连接若未连接则关闭管道

if (FALSE == ConnectNamedPipe(g_hPipe,NULL))
{
printf("Connect is failed......\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}
printf("Connect is successful......\n");
printf("Read data is starting......\n");
while(1)
{
memset(buffer,0,MAXDATANUM); //将buffer数组中所有字符清零
if (!(ReadFile(g_hPipe,&buffer,sizeof(buffer),&ReadNum,NULL))) //判断读取操作是否成功  ReadFile作用:从文件指针指向的位置开始将数据读出到一个文件中
{
printf("Read data is closing......\n");
CloseHandle(g_hPipe);        
getchar();
return 0;
}
printf("Receive data is %s\n",buffer);  //如果从命名管道中成功读取数据则打印出接收的数据
Sleep(100);
}
CloseHandle(g_hPipe); //数据传输完成后关闭管道
getchar();
return 0;
}
二、服务器端
       (1)呼叫对服务器的连接函数CreateFile:
原型:HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName, //要打开的文件的名字
_In_ DWORD dwDesiredAccess, //设备访问方式比如:GENERIC_READ或者是GENERIC_WRITE
_In_ DWORD dwShareMode, //共享方式  表示只能接受一个客户端的请求的到来 不需要共享
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全特性NULL
_In_ DWORD dwCreationDisposition, //设置文件操作的要求     在打开一个通信端口时如管道,无论如何都要设置成 OPEN_EXISTING打开现有的管道
_In_ DWORD dwFlagsAndAttributes, //文档属性 FELE_ATTRIBUTE_NORMAL
_In_opt_ HANDLE hTemplateFile   //模板文件 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
);
函数功能:这是一个多功能的函数,可打开或创建以下对象,并返回可访问的句柄
参数类型及说明
lpFileName String,要打开的文件的名字
dwDesiredAccess Long,如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息
dwShareMode Long,零表示不共享; FILE_SHARE_READ 和/或 FILE_SHARE_WRITE 表示允许对文件进行共享访问
lpSecurityAttributes SECURITY_ATTRIBUTES,指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性
dwCreationDisposition Long,下述常数之一:
CREATE_NEW 创建文件;如文件存在则会出错
CREATE_ALWAYS 创建文件,会改写前一个文件
OPEN_EXISTING 文件必须已经存在。由设备提出要求
OPEN_ALWAYS 如文件不存在则创建它
TRUNCATE_EXISTING 将现有文件缩短为零长度
dwFlagsAndAttributes Long,一个或多个下述常数
FILE_ATTRIBUTE_ARCHIVE 标记归档属性
FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式
FILE_ATTRIBUTE_NORMAL 默认属性
FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录
FILE_ATTRIBUTE_READONLY 文件为只读
FILE_ATTRIBUTE_SYSTEM 文件为系统文件
FILE_FLAG_WRITE_THROUGH操作系统不得推迟对文件的写操作
FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作
FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块
FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化
FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化
FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件
也可在Windows NT下组合使用下述常数标记:
SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY
hTemplateFile Long,相当于一个模板,如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性即相当于拷贝的功能
(2)WriteFile将数据发给客户机
原型:BOOL WriteFile(
  HANDLE hFile, // 文件句柄
LPCVOID lpBuffer, // 数据缓存区指针
DWORD nNumberOfBytesToWrite,  // 要写的字节数
LPDWORD lpNumberOfBytesWritten, // 用于保存实际写入字节数的存储区域的指针
LPOVERLAPPED lpOverlapped // OVERLAPPED结构体指针   如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL
);

客户端代码:

#include <stdio.h>

#include <Windows.h>
#define PIPENAME0 "//./Pipe/Test" //管道名
#define MAXDATANUM 1024
int main()
{
int iData = 0;
char buffer[1024];
DWORD WriteNum = 0;        //写入的字节数初始为0
HANDLE g_hPipe = INVALID_HANDLE_VALUE;
printf("Client of name pipe is testing....\n");
/*获取命名管道句柄*/   
g_hPipe = CreateFile(PIPENAME0, GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //呼叫对服务器的连接对应的是服务器里函数ConnectNamedPipe等待客户机连接请求从而获取到命名管道句柄
//PIPENAME0要打开的文件名  GENERIC_READ | GENERIC_WRITE允许共享即读写 0表示只允许获取与一个设备有关的信息   NULL未定义文件的安全特性
//OPEN_EXISTING 文件已经存在  FILE_ATTRIBUTE_NORMAL默认属性   NULL hTemplateFile为空表示未定义一个模板拷贝文件 


 //判断连接管道是否成功 如果成功则CreateFile函数将返回指向管道的句柄若未成功则关闭管道

if (INVALID_HANDLE_VALUE == g_hPipe)//句柄是否是有效值

{
printf("Get name pipe is failed ....\n");
CloseHandle(g_hPipe);
getchar();
return 0;
}
printf("Send data is beginning....\n");
while (1)
{
memset(buffer,0,MAXDATANUM); //将buffer数组元素全部置0
sprintf(buffer,"%d",iData++);    
printf("Send data is %d\n",iData);   //向客户端写入数据
if (!WriteFile(g_hPipe,buffer,/*(DWORD)*/sizeof(buffer),&WriteNum,NULL))   //进行写操作将数据写入命名管道
{
printf("Send data is closing.....\n");
break;
}
Sleep(100);      
}
CloseHandle(g_hPipe);   //数据传输完毕后关闭命名管道
getchar();
return 0;
}
注:在使用上述代码时,应该先调试服务器端代码再调试客户端的代码

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值