转自:http://blog.sina.com.cn/s/blog_71b3a9690100usem.html

由于自己在写进程间通信的相关程序,查阅了关于资料。觉得命名管道方法实现通信是不错的选择,可是对于其使用方式却有诸多的不解。

同步方式、异步方式、重叠方式………..

有很多的不解。

首先是关于

WaitNamedPipe函数的使用

这个函数的使用感觉有些奇怪,有的地方在用,有的人在写通信程序的使用又没有用。真是其功能甚是不解。

简单的说这个函数就是用来看看有没有可用的管道,若没有管道存在不管等待时间到没有都直接返回错误。若有管道存在且可用,也是直接返回。

不过返回的是正确。若没有空闲的管道(注意是没有空闲,而不是说不存在)则等待规定的时间。一般我们会给指定两种值:

NMPWAIT_USE_DEFAULT_WAIT(等待默认的等待时间,这个值时的等待时间 是在使用创建管道的函数CreateNamedPipe时的倒数第二个参数中指定)

NMPWAIT_WAIT_FOREVER(永远等待,要么是成功等到了有可用的管道。要么是没有管道存在返回错误)

   1:  HANDLE CreateNamedPipe(  LPCTSTR lpName,         // pointer to pipe name
   2:    DWORD dwOpenMode,       // pipe open mode
   3:    DWORD dwPipeMode,       // pipe-specific modes
   4:    DWORD nMaxInstances,    // maximum number of instances
   5:    DWORD nOutBufferSize,   // output buffer size, in bytes
   6:    DWORD nInBufferSize,    // input buffer size, in bytes
   7:    DWORD nDefaultTimeOut,  // time-out time, in milliseconds
   8:    LPSECURITY_ATTRIBUTES lpSecurityAttributes  // pointer to security attributes
   9:  );

另外还要说明的这一个函数不是真正的用于连接。不是说调用它后若是成功返回则表明连接建立。其实不然,从字面意思理解与一般的wait函数相比较。

则知道它的作用只是等待某个事情的发生(不用事件,用‘事情’更形象)。这里等待的是有可用管道实例这一个事实发生。

所以说它返回不代表连接已经建立。相反,还要在它正确返回后用CreateFile和CallNamePipe两个函数之一来建立一个与命名管道服务器端的连接。

MSDN中有说在createfile后正式与管道建立连接。但是在WaitForNamedPipe返回正确时,CreateFile也可能出现错误。不能建立连接。因为在此期间

有可能管道关闭不能再使用。也有可能其它的客户端把可用管道实例给占用完了不能再建立连接。

上面说的是这个函数的作用。也说了一般用法:先用WaitForNamedPipe来等待一个可用的服务器端管道。然后再用CreateFile或者是CallNamedPipe来

建立与管道的连接。同时也要处理可能出现的问题与错误。但是msdn中还用了另外一种这些函数的调用时序。

正如上我所说的一样,在用CreateFile来连接一个可用管道时,调用这个WaitForNamedPipe不是必须的。可以直接用CreateFile来连接管道。而不必管

WaitForNamedPipe这个函数到底是做什么的。这个时候我们可以看下面的一段msdn的说明

A named pipe client uses the CreateFile function to open a handle to a named pipe. If the pipe exists but all of its instances are busy,

CreateFile returns INVALID_HANDLE_VALUE and the GetLastError function returns ERROR_PIPE_BUSY. When this happens, the named pipe

client uses the WaitNamedPipe function to wait for an instance of the named pipe to become available.

The CreateFile function fails if the access specified is incompatible with the access specified (duplex, outbound, or inbound) when the server

created the pipe. For a duplex pipe, the client can specify read, write, or read/write access; for an outbound pipe (write-only server), the

client must specify read-only access; and for an inbound pipe (read-only server), the client must specify write-only access.

说明:CreateFile可以用以建立连接,若有管道且空闲,返回成功。若有管道且所有可用实例都被打开则会返回失败。错误代码为ERROR_PIPE_BUSY。

此时可以用WaitForNamedPipe来等待管道空闲下来。若CreateFile失败,且返回的错误代码为:ERROR_FILE_NOT_FOUND(0x02)说明没有管道存在

因此使用时的顺序应该为先用CreateFile来尝试连接 一下管道 ,看是否成功,若不成功错误错码是什么。若是busy则此时可以调用WaitForNamedPipe来等待其

可用 。若真的不存在则可以直接错误返回了。

ConnectNamedPipe函数的使用

这个函数的使用大家可能也有很多的疑问。如孙鑫的书中有提到说这一个函数应该以Waitxx开始更符合其功能。它就是等待一个客户端的连接,若是阻塞模式则

会等待到真正的在另外一端(客户端)用CreateFile或者是CallNamePipe来创建连接才返回。不过通过实验发现,这个函数管道并不是要用这一个函数来等待,客户端

才能与之进行连接。可以试验一下创建一个字节模式的管道后,不调用它,先把主线程暂停一下。在客户端直接用CreateFile来连接它,发现可以直接连接它,且可以往里面

写数据。此时再用ConnectNamedPipe函数时会发现错误,若仔细查阅其错误代码会发现为ERROR_PIPE_CONNECTED。说明为管道的另一端有进程,也就是说连接已经

建立起来了。所以这个函数的使用也比较的诡异。这个也是要注意的地方

一般用法为CreateNamedPipe来创建管道后调用ConnectNamedPipe来等待别人的连接。(而别人是用CreateFile来建立连接的)

管道的字节模式与消息模式

这个是我最想说的,也是我写这篇文章的目的所在。因为不明白在PIPE_TYPE_BYTE与PIPE_TYPE_MESSAGE间到底有什么区别。

关于怎么样使用管道的中文资料还真是蛮多的,可是你会发现那些东西都是千篇一律的。感觉中国的东西就是天下东西一大抄了。MSDN对消息模式的解释很 少,以至于大家直接翻译msdn的英文意思,也不说个所以然出来,当然可能大家都不知道所以然啦,另外也可能是他们真的用不到,或者是他们的不求甚解。

后来自己探索发现:

两都间没有太大的区别,只是在字节模式的时候是以字节流接收与发送的。每次可以发送不同的字节数,在没有把发送的数据收走(用ReadFile)前也可以再次发送,只要没有超过管道的默认的缓冲区大小 。其实也可以说是我们用的是PIPE_WAIT,所以会是在阻塞模式,也就是说会让数据直接发送到了服务器端的缓冲区中,虽然sever端没有调用ReadFile来读取数据,其实已经发到那一边去了,它不读出来没有关系,我们客户端还是可以继续发送数据的。而且对每次发送的数据大小没有限制,不会说每次都得发送固定大小的数据 。读的那一端也会把接收到的数据作为一个无机的整体,也就是说是没有结构的二进制流。读的时候可以想读出任意的字节数都可以的。如一次发送了5个字节,然后再发送了40个字节 ,服务器端可以一次性全部读出45个字节 也可以每次读出一个字节 。以及小于45的任意字节。

而对于消息模式的话,对于写的大小与次数也没有限制。只是说若是以消息模式写的,则会发给服务器的时候说,这是一个消息,若你用消息模式读的话不能只读其中的一部分。你得全部都读走,若有一个消息发到了服务器端,10个字节。现在你读了8字节(用ReadFile函数)会返回错误,错误代码为ERRORM_More_data.也就是说即是没有超过缓冲区中已有的数据,你没有读够也会不让你读成功。

注意:以消息模式发送的数据,在服务器端 是可以用字节模式接收的,如上所说。若是这样的话也会把有格式的消息化为没有格式的字节流。

但是,不能以消息模式来读取以字节模式发送的消息。

转载于:https://www.cnblogs.com/duyy/p/3738610.html

命名管道的使用方式:消息模式/字节模式相关推荐

  1. 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .

    命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...

  2. 使用命名管道的OVERLAPPED方式实现非阻塞模式编程

    命名管道是进程间通讯的一种常用方式,对于命名管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...

  3. 进程间通信 - 命名管道实现

    引子 好,到这里呢,就需要介绍实现进程间通信的第四种方式了, 也就是通过命名管道来实现,前面介绍的那三种方式呢,都是有缺陷或者说局限性太强, 而这里介绍的命名管道相对来说,在这方面就做得好很多了, 比 ...

  4. linux 命名管道 c语言 不同进程,进程间通信 - 命名管道实现

    命名管道概述 命名管道是通过网络来完成进程之间的通信的,命名管道依赖于底层网络接口, 其中包括有 DNS 服务,TCP/IP 协议等等机制,但是其屏蔽了底层的网络协议细节, 对于匿名管道而言,其只能实 ...

  5. windows命名管道

    命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节. 将命名管道作为一种网络编程方案时,它实际上建立了一个C/S通信体系,并在其中可靠的传输数据.命名管道服务器和客户机的区别在于:服务器 ...

  6. 【Linux】进程间通信 - 匿名/命名管道与System V共享内存

    目录 前言 一.管道 0.什么是管道 1).管道的概念 2).管道的本质 3).管道指令: "|" 1.匿名管道 1).如何创建匿名管道 2).如何使用匿名管道进行通信 3).匿名 ...

  7. windows命名管道使用方法

    原文地址:https://www.cnblogs.com/lsh123/p/7435401.html 命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节. 将命名管道作为一种网络编程方案 ...

  8. linux命名管道进程间通信,Linux进程间通讯--命名管道

    IPC安全 前面总结了匿名管道,如今来看命名管道:因为匿名管道的一个限制就是:只能是有血缘关系的进程间才能够通讯,好比:有两个同祖先的子进程,父子进程等:为了突破这一个限制,想让没有任何关系的两个进程 ...

  9. 进程间通信(7) “剪贴板“、“匿名管道“、“命名管道“、“邮槽“4种方式总结

    1. 剪贴板和匿名管道只能同一-台机器上 命名管道和邮槽还可以实现跨网络的进程间通信; 邮槽是基于广播通信的,可以一对多的单向通信, 数据量较小,通常都是在424字节以下 命名管道只能点对点的单一的通 ...

最新文章

  1. Android自定义控件(四)仿网易客户端上拉加载更多
  2. 【机器学习基础】机器学习中必知必会的 3 种特征选取方法!
  3. linux 6.7 nfs安装yum,centos6.7下安装配置NFS
  4. OSChina 周一乱弹 ——程序员用代码写的爱情
  5. DWR的学习文档(Hello World,类型转换,Spring,Annotation)
  6. Oracle启动操作
  7. php pdo 预处理删除,PHP PDO扩展整理,包括环境配置\基本增删改查\事务\预处理
  8. 个人DP训练(基础版)
  9. spring gateway 限流持久化_Spring Cloud Gateway网关如何快速实施限流方案?-Part 6
  10. apache http server 停止工作_Springboot以Tomcat为容器实现http重定向到https的两种方式
  11. 剑指Offer值数字在排序数组中出现的次数
  12. 网页html跑马灯,web实现跑马灯
  13. c#生成Excel饼图、柱状图
  14. 缓冲流、转换流、序列化流、装饰设计模式、comms-io工具包
  15. PostgreSQL+PostGIS下载和离线安装
  16. 【Spring Boot】——集成JSON工具
  17. 房子装饰风水有哪些讲究和忌讳
  18. Android 仿自如APP裸眼3D效果
  19. pandas处理excel单元格合并后的列
  20. [ukulele]入门指南

热门文章

  1. linux+fstab挂载镜像,通过/etc/fstab自动挂载iso镜像的ISO格式问题
  2. 样本修改 sample_如何在R中使用sample()获取样本?
  3. groupdel 删除组_如何在Linux中删除组– groupdel命令
  4. python多重继承_Python多重继承
  5. struts2异常处理流程_Struts2异常处理示例教程
  6. C语言基础教程之常量
  7. 新书推荐:可爱的Python
  8. 高逼格的程序员这样度过十一假期
  9. 计算指定人数班级的班级平均成绩(计数器控制控制的循环)
  10. UIWindow的rootViewController的问题