17.3.3 客户端程序.txt
来自「网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节」· 文本 代码 · 共 152 行
TXT
152 行
17.3.3 客户端程序
接下来创建命名管道的客户端程序。同样,可以将客户端程序添加到已有的服务器程序所在的工作
区: NamedPipeSrv中,所以,在此工作区中新建一个单文档类型的 MFC应用程序,工程取名为:
NamedPipeClt,同时设置该工程所在的目录与 NamedPipeSrv工程的目录平级。
然后,为该工程增加一个子菜单,菜单名称为"命名管道"。接着,为该子菜单添加三个菜单项,并
分别为它们添加相应的命令响应函数,本例选择 CNamedPipeCltView类接收这些命令响应函数。各
菜单项的 B、名称,以及响应函数如表 17.14所示。
表 17.14添加的菜单项及相应的晌应函数
ID 菜单名称 响应函数
IDM_PIPE_CONNECT 连接管道 OnPipeConnect
IDM PIPE READ 读取数据 OnPipeR四d
IDM PIPE WRITE 写入数据 OnPipeWrite
接下来,为 CNamedPipeCltView类增加一个句柄变量,用来保存命名管道实例的句柄。
private:
HANDLE hPipe;
同样地,在 CNamedPipeCltView类的构造函数中将其初始化为 NULL:
CNarnedPipeCltView:: CNarnedPipeCltView ()
{ 11 TODO: add construction code here hPipe =NULL;
然后,在 CNamedPipeCltView类的析构函数中,如果判断该句柄有值,则调用 CloseHandle关闭该
句柄:
CNamedPipeCltView: : -CNamedPipeCltView. ()
if (hPipe)
CloseHandle(hPipe);
.
1.连接命名管道
客户端在连接服务器端程序创建的命名管道之前,首先应判断一下,是否有可以利用的命名管道,
这可以通过调用WaitNamedPipe函数实现,该函数会一直等待,直到指定的超时间隔己过,或者指定
的命名管道的实例可以用来连接了,也就是说该管道的服务器进程有了一个未决的
ConnectNamedPipe操作。 WaitNamedPipe函数的原型声明如下所示:
BOOL WaitNamedPipe(LPCTSTR lpNamedPipeName , DWORD nTimeOut) ;
该函数有两个参数,各自的含义分别如下所述。
. lpNamedPipeName
指定命名管道的名称,这个名称必须包括创建该命名管道的服务器进程所在的机器的名称,该名称
的格式必须是:"\.\pipe\pipename"。如果在同一台机器上编写的命名管道的服务器端程序和客户
端程序,则当指定这个名称时,在开始的两个反斜杠后可以设置一个圆点,表示服务器进程在本地
机器上运行;如果是跨网络通信,则在这个圆点位置处应指定服务器端程序所在的主机名。
. nTimeOut
指定超时间隔。其取值如表17.15所示。
表17.15 nTimeOut参数取值
取值 说明
NMPWAIT USE DEFAULT WAIT 超时间隔就是服务器端创建该命名管道时指定的超时值
NMPWAIT WAIT FOREVER 一直等待,直到出现了一个可用的命名管道的实例
也就是说,如果这个参数的值是~PWA1T_USE_DEFAULT_WA1T,井且在服务器端调用 CreateNamedPipe
函数创建命名管道时,设置的超时间隔为 IOOOms,那么 WaitNamedPipe函数将以服务器端指定的
1000ms为超时间隔。但有一点需要注意,对同一个命名管道的所有实例来说,它们必须使用同样的
超时间隔。
如果当前命名管道的实例可以使用,那么客户端就可以调用CreateFile函数打开这个命名管道,与
服务器端进程进行通信了。因此,客户端的连接命名管溢的代码如例 17-12所示。
1~IJ 17-12
void CNamedPipeCltView::OnPipeConnect()
// TODO : Add your command handler code here
//判断是否有可以利用的命名管道
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 ( n打开命名管道失败!");
hPipe=NULL;
return;
在如例 17-12所示的OnPipeConnect函数中,首先调用WaitNamedPipe函数,将其超时值设置为
NMPWAIT_WAIT_FOREVER,即让该函数一直等待,直到指定的命名管道的一个实例可以利用时为止。
并对WaitNamedPipe函数的返回值进行判断,如果该函数调用失败,即返回值是0,则提示用户="当
前没有可利用的命名管道实例!",然后立即返回。
如果当前指定命名管道有一个实例可以使用,那么就调用 CreateFile函数打开该命名管道。前面介
绍 CreateFile函数时己经提到,该函数不仅可以对文件进行操作,还可以对管道进行操作。当然,
这里指定的文件名就是想要访问的管道名称:并且为了对管道进行读取和写入操作,需要同时指定
GENE阳已阻AD和GENE阳C-wm四这两种访问方式; CreateFile函数的第三个参数用来指定共享方式,
因为本例中,该管道实例只能接受一个客户端请求的到来,不需要共享,因此将该参数设置为 0;
第四个参数是设置安全属性,本例将其设置为NULL;第五个参数是指定创建标记,本例将其设置为
OPEN_EXIST剧G,即打开现有的管道:第六个参数是指定文件属性,本例将其指定为 FILE
ATIRBIJTE-NORMAL;最后一个参数是指定模板文件,本例将其设置为NULL。
如果CreateFile函数调用失败,返回值将是因VALlD_HANDLE_VALUE。因此,如果判断该函数的返回
值是剧VALID_HANDLE_VAL阻,则提示用户:"打开命名管道失败!",并将管道句柄 ChPipe)设置为
NULL,然后立即返回。
2.读取数据
如果客户端成功打开了指定的命名管道,那么就可以进行读取和写入操作了。这里,我们可以直接
复制上面服务器端己编写的从命名管道读取数据的代码,结果如例17-13所示。
fJ~ 17-13
void CNamedPipeCltView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf , 100 ,&dwRead ,NULL))
MessageBox(n读取数据失败!");
return;
MessageBox(buf) ;
3.写入数据
这里,我们可以直接复制上面服务器端己编写的向命名管道写入数据的代码,但为了加以区分,将
客户端写入的数据修改为 26‘命名管道测试程序飞即客户端向命名管道写入数据的代码如例 17-14
所示。
例 17-14
void CNamedPipeCltView::OnPipeWrite()
// TODO: Add your command handler code here
char buf [ 1= "命名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hPipe, buf , strlen(buf)+1 , &dwWrite ,NULL))
{
MessageBox("写入数据失败!");
return;
至此我们就完成了利用命名管道实现进程间通信的客户端程序,利用 Build命令生成 NamedPipeClt
程序。
因为采用命名管道实现进程间的通信时,通信的两个进程间不需要有任何关系,所以可以独立地运
行 NamedPipeSrv和 NamedPipeClt这两个进程,然后在服务器端单击 E命名管道\创建管道】菜单
项创建指定的命名管道,在客户端进程中单击【命名管道\连接管道】菜单项连接到这个命名管道:
接着在服务器端单击【命名管道飞写入数据】菜单项向命名管道中写入数据,在客户端单击【命名
管道飞读取数据】菜单项从命名管道读取数据,这时客户端将弹出一个消息框,提示收到一个网址
字符串: ''http://www.sunxin.org'',程序运行界面如图 17.6所示。当然,也可以由客户端进程
写入数据,服务器端进程读取数据,即单击客户端程序的【命名管道飞写入数据】菜单项向命名管
道中写入数据,然后在服务器端单击【命名管道飞读取数据】菜单项从命名管道读取数据,这时服
务器端将弹出一个消息框,提示收到"命名管道测试程序"字符串,程序运行界面如图 17.7所示。
以上就是采用命名管道完成进程间通信的实现,具体过程是:在服务器端调用 CreateNamedPipe创建
命名管道之后,调用 ConnectNamedPipe函数让服务器端进程等待客户端进程连接到该命名管道的实
例上。在客户端,首先调用 WaitNamedPipe函数判断当前是否有可以利用的命名管道实例,如果有,
就调用 CreateFile函数打开该命名管道的实例,并建立一个连接。
......... 1655
第17
E皿函
文件巳搞错(0 .警('fJ幌酣)(!J)命名智;置也
Dt.声匾吁 .&~ .r~画!
Y
戳" 性悟,,,..附.锐....,.01'。嚣'
眼l
{
就精 黯蟠 '-.
EZ
图 17.6利用命名管道实现进程间图 17.7利用命名管道实现进程间
通信的程序结果(一)通信的程序结果〈二〉
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?