标签:
本文转自:
程序源码及实验报告文档下载:http://download.csdn.net/detail/xiaowei_cqu/3880949
命名管道
进程间通信的一种方式,Pipes:管道,分为无名管道:在父子进程间交换数据;有名管道:可在不同主机间交换数据,分为服务器方和客户方,在Win9X下只支持有名管道客户。
命名管道的命名
命名管道是一个有名字的,单向或双向的通信管道。管道的名称有两部分组成:计算机名和管道名,例如\\[host_name]\pipe\[pipe_name]\(括号内为参数)。对于同一主机来讲允许有多个同一命名管道的实例并且可以由不同的进程打开,但是不同的管道都有属于自己的管道缓冲区而且有自己的通讯环境互不影响,并且命名管道可以支持多个客户端连接一个服务器端。命名管道客户端不但可以与本机上的服务器通讯也可以同其他主机上的服务器通讯。
命名管道的连接
在服务器端第一次创建命名管道后等待连接,当客户端连接成功后服务器端的命名管道就用作通讯用途。如果需要再次等待连接,服务器端就需要再次打开命名管道(创建一个命名管道的实例)并等待连接。
对于客户端每次打开命名管道后建立与服务器间的连接,然后就可以利用命名管道进行通信,如果需要建立第二个连接则需要再次打开管道和再次建立连接。
创建命名管道时需要指定一个主机名和管道名,对于客户端来说可以是如下格式:\\[host_name]\pipe\[pipe_name]\也可以是\\.\pipe\pipe_name\其中.表示本机。而服务器端只能够在指定本机作为主机名,即只能使用下面的格式:\\.\pipe_name\。此外需要记住,在同一主机上管道名称是唯一的,一个命名管道一旦被创建就不允许相同名称的管道再被创建。
主要函数
管道服务器首次调用CreateNamedPipe()函数时,使用nMaxInstance参数指定了能同时存在的管道实例的最大数目。服务器可以重复调用CreateNamedPipe()函数去创建管道新的实例,直至达到设定的最大实例数。
服务器方通过该函数创建命名管道和打开已经存在的命名管道,其中lpName为管道名称,dwOpenMode为创建方式,可以是下面值的组合:
PIPE_ACCESS_INBOUND:管道只能用作接收数据。
PIPE_ACCESS_OUTBOUND:管道只能用作发送数据。
PIPE_ACCESS_DUPLEX:管道既可以发送也可以接收数据。(上面这三个值只能够取其中一个)
FILE_FLAG_WRITE_THROUGH:管道用于同步发送和接收数据,只有在数据被发送到目标地址时发送函数才会返回,如果不设置这个参数那么在系统内部对于命名管道的处理上可
能会因为减少网络附和而在数据积累到一定量时才发送,并且对于发送函数的调用会马上返回。
管道的连接管理,客户方在调用CreateFile后立即就能够建立服务器的连接,而服务器方一旦管道打开或创建后可以用
来等待客户端的连接建立。如果希望在服务器方检测是否有连接到达,可以调用
BOOL WaitNamedPipe( LPCTSTR lpNamedPipeName, // pipe name DWORD nTimeOut // time-out interval );
这里的lpNamePipeName直接使用创建管道时的名称,如果在服务器方希望关闭连接则调用
BOOL DisconnectNamedPipe( HANDLE hNamedPipe // handle to named pipe );
一旦连接被关闭,服务器方可以再次调用ConnectNamedPipe来建立连接。如果要关闭管道则直接调用CloseHandle。请注意这里提到的关闭管道和关闭连接是不同的意思,在同一个管道上可以依次反复建立连接,而且可以减小系统的负荷。而且如果指定了管道最大数量限制那么在打开的管道达到最大限制后如果不关闭旧管道就无法打开新管道。 对于客户方则无法关闭连接,而只能直接调用CloseHandle关闭管道。
数据的发送,不论是服务器还是客户方都可以通过ReadFile和WriteFile进行管道读写来达到通讯的目的。
不管用什么方式进行编码和解码,需要两个进程能够相互传递
1.查阅有关进程间通信的资料
用管道实现进程间通信,需要编写服务器及客户端。
服务器端设计:
参考网址:http://www.cnblogs.com/xinhaijulan/archive/2010/07/28/1786535.html
http://www.cnblogs.com/wangyonghui/archive/2010/01/24/1655390.html
2.定义要传递的数据结构
3.客户端代码
在实验一的基础上,客户端使用两个线程,一个线程中实例一个客户端,使用管道通信向客户端发送数据(数据结构转为string类型);另一个线程中接收服务器端管道中的数据,再将string转为定义的数据结构。
4.数据结构与string相互转化的函数
服务器端输出截图:
客户端截图:
实验的大部分地方都是用try catch来处理异常,catch中通过MessageBox显示可以很快看到错误问题。实验中遇到:
网上查阅了一些资料,了解信号灯也是进程间通信的一种方式。“信号灯与其它进程间通信方式有所不同,它主要用于进程间同步。通常所说的系统V信号灯实际上是一个信号灯的集合,可用于多种共享资源的进程间同步。每个信号灯都有一个值,可以用来表示当前该信号灯代表的共享资源可用(available)数量,如果一个进程要申请共享资源,那么就从信号灯值中减去要申请的数目,如果当前没有足够的可用资源,进程可以睡眠等待,也可以立即返回。”(http://www.cnblogs.com/thinkingworld/articles/1861739.html)
不少人遇到过这个故障(数据库中或硬盘读盘),但最终还是没有读懂,不知道自己为什么会遇到这个问题。猜测可能还是不同线程向窗口写入东西(改变空间属性)引起的问题。于是将输出的信息改为一次性输出,暂时没有再出现问题。(具体见代码中注释)
标签:
原文地址:http://www.cnblogs.com/mydish/p/4340860.html