Windows命名管道和应用程序

电脑杂谈  发布时间:2020-07-25 18:03:18  来源:网络整理

创建命名管道_成都哪儿有卖自来水管道堵漏器,管道修补器_管道命名

管道实际上是用于进程间通信的共享内存. 创建管道的过程称为管道服务器,连接到管道的过程是管道客户端. 命名管道是一种命名管道,用于管道服务器和一个或多个管道客户端之间的单向或双向通信. 命名管道的所有实例共享相同的管道名称,但是每个实例具有独立的缓存和句柄,并提供用于客户服务通信的单独管道. 使用实例可确保多个管道客户端可以同时使用同一个命名管道.

Microsoft Windows NT,Windows 2000,Windows 95和Windows 98均提供对命名管道的支持(不包括Windows CE),但是仅Windows NT和Windows 2000支持服务器端命名管道技术. 命名管道可以连接在同一计算机上的不同进程之间,或者可以跨网络连接在不同计算机上的不同进程之间. 如果连接中断,双方都可以立即收到断开连接消息. . 命令管道是围绕Windows文件系统设计的一种机制,该机制使用命名管道文件系统(命名管道文件系统,NPFS)接口. 数据的发送和接收还使用文件读取和写入功能ReadFile()和WriteFile()完成. 在设计中,由于命名管道还使用Microsoft网络提供程序(MSNP)重定向器,因此无需涉及基础通信协议的详细信息. 命名管道还充分利用了Windows NT和Windows 2000的内置安全功能,并且通信的安全性相对较好.

每个命名管道都有一个唯一的名称,以区别于系统命名对象列表中的其他命名管道. 管道服务器在调用CreateNamedPipe()函数以创建一个或多个命名管道实例时分配了一个名称. 对于管道客户端,在调用CreateFile()或CallNamedPipe()函数以连接到命名管道实例时指定管道名称. 命名管道的命名约定类似于邮件插槽的命名约定,并且其标识也采用UNC格式: \\ ServerName \ pipe \ PipeName

其中,第一部分\\ ServerName指定服务器的名称,在此服务器上创建了命名管道服务,其字符串部分可以表示为小数点(表示此机器),星号(当前网络字段),域名或真实服务管道名称,长度可以达到256个字符;第二部分\ Pipe是不可更改的硬编码字符串,例如邮筒的\ Mailslot,表示该文件属于NPFS;第三部分PipeName的使用该应用程序可以唯一地定义和标识命名管道的名称,并可以建立多级目录.

当管道服务器端调用CreateNamedPipe时,可以通过dwOpenMode指定管道的访问,重叠和直写模式,并且使用CreateFile时,相应的命名管道客户端可以指定相应的模式. 有关详细信息,请参见: (v = vs.85).aspx

命名管道提供两种基本的通信模式: 字节模式和消息模式. 在CreateNamePipe()中创建命名管道时,可以使用PIPE_TYPE_BYTE和PIPE_TYPE_MESSAGE标志设置dwPipeMode参数. 在字节模式下,信息以连续字节流的形式在客户端和服务器之间流动. 这也意味着对于客户端应用程序和服务器应用程序,不可能确切知道在任何特定时间段内从管道读取或写入了多少字节. 在这种通信模式下,当一方将一定数量的字节写入管道后,无法保证管道上的另一方可以读取相同数量的字节. 对于消息模式,客户端和服务器通过一系列不连续的数据包发送和接收数据. 从管道发送的每条消息都必须作为完整的消息读入.

管道客户端和服务器都可以通过SetNamedPipeHandleState更改管道句柄的读取模式(PIPE_READMODE_MESSAGE,PIPE_READMODE_BYTE)和等待模式(PIPE_NOWAIT,PIPE_WAIT).

管道服务器首次调用CreateNamedPipe()函数时,它使用nMaxInstance参数指定可以同时存在的最大管道实例数. 服务器可以重复调用CreateNamedPipe()函数来创建管道的新实例,直到达到设置的最大实例数. 下面给出了CreateNamedPipe()的函数原型:

HANDLE CreateNamedPipe(

LPCTSTR lpName,//指向管道名称的指针

DWORD dwOpenMode,//管道打开模式

DWORD dwPipeMode,//管道模式

DWORD nMaxInstances,//最大实例数

DWORD nOutBufferSize,//输出缓冲区大小

DWORD nInBufferSize,//输入缓冲区大小

DWORD nDefaultTimeOut,//超时设置

LPSECURITY_ATTRIBUTES lpSecurityAttributes //指向安全属性的指针

);

如果在定义的超时值变为零之前可以使用实例管道,则创建成功并且管道句柄将返回以侦听来自客户端的连接请求. 另一方面,客户端使用功能WaitNamedPipe()来使服务器进程等待来自客户端的实例连接. 如果在超时值变为零之前有可用的连接管道,则该函数将成功返回并通过调用CreateFile()或CallNamedPipe()来调用与服务器的连接. 此时,服务器将接受客户端的连接请求并成功建立连接. 服务器调用以等待客户端建立连接的ConnectNamedPipe()函数也将成功返回.

从调用顺序的角度来看,首先,客户端使服务器的CreateFile()通过WaitNamedPipe()在有限的时间内成功创建实例,然后双方通过ConnectNamedPipe()和CreateFile()成功连接,返回文件后,客户端和服务器即可通信.

建立连接后,客户端和服务器可以通过ReadFile()和WriteFile()并使用获得的管道句柄以文件读写的形式相互交换信息. 当客户端和服务器之间的通信结束时,或者当一方由于某种原因需要断开连接时,客户端将调用CloseFile()函数以关闭打开的管道句柄,然后服务器将调用DisconnectNamedPipe()函数. 当然,服务器也可以通过单方面调用DisconnectNamedPipe()来终止连接. 终止连接后,调用函数CloseHandle()关闭管道.

摘要: 主线程创建一个命名管道实例,并等待命名管道客户端建立连接. 当命名管道客户端建立连接时,管道服务器会创建一个线程来为客户端提供服务.

管道服务器代码摘要:

首先获取主线程的真实句柄值

dwRet = :: DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),&hMainThread,0,FALSE,DUPLICATE_SAME_ACCESS);

创建一个退出线程,并将主线程的实际句柄用作参数:

HANDLE hExitThread = reinterpret_cast(_beginthreadex(NULL,uiDefStackSize,ExitThread,hMainThread,0,NULL));

在主循环中,首先通过SleepEx将主循环置于Alertable状态,以便在退出线程中,可以通过QueueUserAPC通知主线程退出,创建命名管道实例,并阻塞等待客户端连接通过CreateNamedPipe:

while(true)

{

dwRet = SleepEx(1,TRUE);

if(dwRet == WAIT_IO_COMPLETION)

{

休息;

}

hPipe = CreateNamedPipe(g_namedpipe_name,

PIPE_ACCESS_DUPLEX,

PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,

PIPE_UNLIMITED_INSTANCES,

BUFSIZ,

BUFSIZ,

成都哪儿有卖自来水管道堵漏器,管道修补器_创建命名管道_管道命名

0,

NULL);

if(hPipe == INVALID_HANDLE_VALUE)

{

printf(“创建命名管道失败创建命名管道,错误=%d \ n”,GetLastError());

休息;

}

g_hPipe = hPipe;

//等待客户端连接;如果成功,

//该函数返回一个非零值. 如果功能

//返回零,GetLastError返回ERROR_PIPE_CONNECTED.

bConnected = ConnectNamedPipe(hPipe,NULL)? TRUE: (GetLastError()== ERROR_PIPE_CONNECTED);

if(bConnected)

{

//为此客户端创建一个线程.

hThread = reinterpret_cast(_beginthreadex(NULL,uiDefStackSize,WorkerThread,(LPVOID)hPipe,0,NULL));

如果(hThread == NULL)

{

printf(“ CreateThread失败,错误=%d \ n”,GetLastError());

返回0;

}

其他

{

//分离的线程

CloseHandle(hThread);

}

}

其他

{

//客户端无法连接,因此请关闭管道.

CloseHandle(hPipe);

}

}

退出线程中的循环:

while(true)

{

std :: getline(std :: cin,name);

if(name ==“ quit”)

{

/// @ note: 首先,我们应该取消同步io(connectnamedpipe)函数

CancelSynchronousIo(hMainThread);

创建命名管道_管道命名_成都哪儿有卖自来水管道堵漏器,管道修补器

/// @ note: 然后我们应该通知主线程退出.

QueueUserAPC(Aroc,hMainThread,NULL);

休息;

}

其他

继续;

}

用户进入quit后,CancelSynchronousIo首先取消所有阻塞的IO操作,然后QueueUserAPC通知主线程退出.

有关详情,请参见(v = vs.85).aspx

摘要: 管道服务器首先创建一个完成端口对象,然后创建多个Pipe实例,将这些实例与完成端口相关联,并通过调用ConnectNamedPipe ReadFile,WriteFile和其他方法传递OVERLAPPED非空对象参数以提交异步请求接口. 通过线程循环中的GetQueuedCompletionStatus获取提交的异步请求的结果.

管道服务器代码摘要:

创建完成的端口:

:: CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,NULL,1);

创建一个退出线程. 退出线程收到用户输入的“退出”后,它将通知完成端口线程池通过PostQueuedCompletionStatus退出. 由于完成端口线程池的数量为1,因此只需调用一次即可:

HANDLE hExitThread = reinterpret_cast(_beginthreadex(NULL,uiDefStackSize创建命名管道,ExitThread,NULL,0,NULL));

通知主线程退出:

std :: getline(std :: cin,name);

if(name ==“ quit”)

{

:: PostQueuedCompletionStatus(hIocpPort,0,0,(LPOVERLAPPED)&exitOverlapped);

休息;

}

在main函数中创建一定数量的管道设备对象,并将它们与完成端口相关联,并通过ConnectNamedPipe提交异步客户端连接请求:

对于(DWORD i = 0; i

{

Pipe [i] .hPipeInst = CreateNamedPipe(

lpszPipename,//管道名称

PIPE_ACCESS_DUPLEX | //读/写访问权限

FILE_FLAG_OVERLAPPED,//重叠模式


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-288048-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...