java与c 命名管道_C/S模型之命名管道

说明:利用管道实现服务端与客户端之间的交互。效果等同于利用socket。

命名管道(NamedPipe)是一种简单的进程间通信(IPC)机制,是服务器进程和一个或多个客户进程之间通信的单向或双向管道。

其本质是文件读写、内存共享。

采用命名管道完成进程通信的过程为:

1.在服务器端调用CreateNamedPipe创建命名管道之后,调用ConnectNamedPipe函数让服务器进程等待客户端进程连接到该命名管道的实例上。

2.在客户端,首先调用WaitNamedPipe函数判断当前是否有可以利用的命名管道实例,如果有就调用CreateFile函数打开该命名管道的实例,并建立一个连接。

之后就可以通过ReadFile、WriteFile进行通信。

函数讲解:

第一个CreateNamedPipe

函数功能:创建命名管道

函数原型:

HANDLEWINAPICreateNamedPipe(

LPCTSTRlpName,

DWORDdwOpenMode,

DWORDdwPipeMode,

DWORDnMaxInstances,

DWORDnOutBufferSize,

DWORDnInBufferSize,

DWORDnDefaultTimeOut,

LPSECURITY_ATTRIBUTESlpSecurityAttributes

);

参数说明:

第一个参数LPCTSTRlpName

表示管道名称,采用的形式是:\\.\pipe\pipename。最多可达256个字符的长度,而且不区分大小写。如果已经有同名管道,则会创建那个管道的一个新实例。

第二个参数DWORDdwOpenMode

表示管道的打开方式。下面列出最常用的三种,更多请参阅MSDN。

1.PIPE_ACCESS_DUPLEX

该管道是双向的,服务器和客户端进程都可以从管道读取或者向管道写入数据。

2.PIPE_ACCESS_INBOUND

该管道中数据是从客户端流向服务端,即客户端只能写,服务端只能读。

3.PIPE_ACCESS_OUTBOUND

该管道中数据是从服务端流向客户端,即客户端只能读,服务端只能写。

第三个参数DWORDdwPipeMode

表示管道的模式,下面是一些常用模式介绍,更多请参阅MSDN。

1.PIPE_TYPE_BYTE

数据作为一个连续的字节数据流写入管道。

2.PIPE_TYPE_MESSAGE

数据用数据块(名为“消息”或“报文”)的形式写入管道。

3.PIPE_READMODE_BYTE

数据以单独字节的形式从管道中读出。

4.PIPE_READMODE_MESSAGE

数据以名为“消息”的数据块形式从管道中读出(要求指定PIPE_TYPE_MESSAGE)。

5.PIPE_WAIT

同步操作在等待的时候挂起线程。

6.PIPE_NOWAIT

同步操作立即返回。

第四个参数DWORDnMaxInstances

表示该管道所能够创建的最大实例数量。必须是1到常数PIPE_UNLIMITED_INSTANCES间的一个值。

在WINBASE.H中有#define PIPE_UNLIMITED_INSTANCES 255

第五个参数DWORDnOutBufferSize

表示管道的输出缓冲区容量,为0表示使用默认大小。

第六个参数DWORDnInBufferSize

表示管道的输入缓冲区容量,为0表示使用默认大小。

第七个参数DWORDnDefaultTimeOut

表示管道的默认等待超时。

第八个参数LPSECURITY_ATTRIBUTESlpSecurityAttributes

表示管道的安全属性。

函数返回值:

函数执行成功返回命名管道的句柄,否则返回INVALID_HANDLE_VALUE。

第二个ConnectNamedPipe

函数功能:等待客户端连接命名管道

函数原型:

BOOLWINAPIConnectNamedPipe(

HANDLEhNamedPipe,

LPOVERLAPPEDlpOverlapped

);

函数说明:

第一个参数表示命名管道的句柄。

第二个参数是一个指向OVERLAPPED结构的指针,一般置为NULL就可以了。

第三个WaitNamedPipe

函数功能:客户端连接命名管道

函数原型:

BOOLWINAPIWaitNamedPipe(

LPCTSTRlpNamedPipeName,

DWORDnTimeOut

);

函数说明:

第一个参数LPCTSTRlpNamedPipeName

表示管道名称,采用的形式是:\\servername\pipe\pipename。如果是本机管道,servername用“.”来表示。

第二个参数DWORDnTimeOut

表示等待命名管道的一个实例有效的超时时间,单位毫秒。也可以用NMPWAIT_USE_DEFAULT_WAIT表示使用命名管道的设定值(在调用CreateNamedPipe创建命名管道时指定的),NMPWAIT_WAIT_FOREVER表示无限等待。

函数返回值:

在指定时间内连接成功返回TRUE,否则返回FALSE。

注意

1:如果指定名称的命名管道还没创建,函数立即返回,返回值为FALSE。

2:如果函数执行成功返回TRUE,表示至少有一个命名管道的实例有效,接下来应该使用CreateFile函数打开命名管道的一个句柄,但是CreateFile可能会打开管道失败,因为该实例有可能被服务端关闭或被已经被其他客户端打开。

服务端和客户端的主要步骤如下所示:

1. 服务端用CreateNamedPipe创建一个命名管道并使用ConnectNamedPipe等待客户端的连接。

2. 客户端使用WaitNamedPipe连接成功后,用CreateFile打开管道并使用WriteFile向管道中写入一段数据(即向服务端发送消息)。

3. 服务端使用ReadFile从管道中读取数据后(即收到消息)再向管道中写入确认信息表明已经收到客户端传输的数据(即通知客户端已收到)。

4. 客户端收到确认信息后结束,调用CloseHandle关闭管道(该管道是CreateFile打开的)。

5.服务端使用DisconnectNamedPipe和CloseHandle关闭管道。

源代码://服务端

#include"stdafx.h"#include

int _tmain(int argc, _TCHAR*argv[])

{const char *szPipeName = "\\\\.\\pipe\\Pipe";//创建命名管道

HANDLE hPipe =CreateNamedPipe(

szPipeName,//pipe name

PIPE_ACCESS_DUPLEX |FILE_FLAG_OVERLAPPED,//read/write access

PIPE_TYPE_MESSAGE | //message type pipe

PIPE_READMODE_MESSAGE | //message-read mode

PIPE_WAIT, //blocking mode

PIPE_UNLIMITED_INSTANCES, //max. instances

MAXBYTE, //output buffer size

MAXBYTE, //input buffer size

0, //client time-out

NULL); //default security attribute

if (hPipe ==INVALID_HANDLE_VALUE)

{

printf("CreateNamedPipe Error :%d", GetLastError());

}char pRecvBuf[MAXBYTE] = { 0};

DWORD dwLen=0;//连接管道

if(ConnectNamedPipe(hPipe, NULL))

{

printf("连接成功,开始接收数据!\n");while (true)

{//取得客户端的数据

if (ReadFile(hPipe, pRecvBuf, MAXBYTE, &dwLen, 0))

{

printf("%s\n", pRecvBuf);

}if (strcmp(pRecvBuf, "exit") == 0)

{break;

}//将收到的数据进行返回

if (WriteFile(hPipe, pRecvBuf, strlen(pRecvBuf) + sizeof(char), &dwLen, 0))

{

}else{break;

}

}

}//关闭管道

DisconnectNamedPipe(hPipe);

CloseHandle(hPipe);return 0;

}

//客户端

#include"stdafx.h"#include

int _tmain(int argc, _TCHAR*argv[])

{const char *szPipeName = "\\\\.\\pipe\\Pipe";//检测是否存在该命名管道

if (WaitNamedPipe(szPipeName, NMPWAIT_WAIT_FOREVER) ==TRUE)

{

printf("连接命名管道成功!\n");

}//打开文件--连接管道

HANDLE hFile = CreateFile(szPipeName, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);char pSendBuf[MAXBYTE] = { 0};char pRecvBuf[MAXBYTE] = {0};

DWORD dwLen= 0;while (true)

{

gets_s(pSendBuf);//将管道传数据

if(!WriteFile(hFile, pSendBuf, strlen(pSendBuf) + sizeof(char), &dwLen, NULL))

{

printf("False\n");

}if (strcmp(pSendBuf, "exit") == 0)

{break;

}//读取管道中的数据

if (ReadFile(hFile, pRecvBuf, MAXBYTE, &dwLen, 0))

{

printf("return :%s \n", pRecvBuf);

}

}//关闭管道

CloseHandle(hFile);return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值