1. pipe管道通信,其实socket也要依赖于它,可以实现双向通信。还能解决并发。
比共享内存和邮槽都靠谱。
2. 禁止一个程序打开多次,也就是锁定一个程序只能打开一次,限制它的打开次数,用管道就 必须这么做,否则会发生冲突。
3.有线程池也有管道池
4.例子
- 服务端
#include <stdio.h> #include <Windows.h> //管道是存在于操作系统 #define SIZE 4096 char pipename[128] = "\\.\Pipe\guandaopipe"; //用这种模式命名等同于设备。 HANDLE m_pipe = NULL; //管道的句柄 //创建一个管道 void start() { m_pipe = CreateNamedPipeA( pipename, //管道名称 PIPE_ACCESS_DUPLEX, //管道的读写属性 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, //消息模式,读模式,等待模式(相当于阻塞模式)PIPE_TYPE_MESSAGE一般情况有两种,用的最多的是消息模式,另一种是二进制模式(BYTE模式)。 PIPE_UNLIMITED_INSTANCES,//同时开启管道的最大个数,最多是255,在服务器上可以开辟更多。 SIZE, //输出(读)的缓冲区大小 SIZE, //输出(写)的缓冲区大小 0, //客户端超时时间 NULL ); if (m_pipe == NULL) { printf("创建失败"); return; } //连接这个管道并且判断是否连上。 BOOL isconnect = ConnectNamedPipe(m_pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); if (isconnect) { MessageBoxA(0, "connected OK", "connected OK", 0); } else { printf("创建失败。"); } } void read() { char buf[SIZE] = { 0 }; //我们有可能把管道的所有信息都读了,初始化时原则上初始为0。 int last = 0; if (!ReadFile(m_pipe, buf, SIZE, &last, NULL)) //Readpipe是纯C语言里边,如果是C的管道库,用Readpipe,C语言把所有的设备当成文件来处理,所以用ReadFile,若返回值是0表示读取失败. { printf("读取失败"); return; } printf(" read%s", buf); } void write() { char str[128] = "举头望明月,这就是管道。"; int last = 0; BOOL res = WriteFile(m_pipe, str, sizeof(str), &last, NULL); if (!res) { printf("写入失败"); } } void test() { //先尝试能不能打开,打开了,就说明原来存在。如果没有打开就创建一个。 HANDLE mutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, "guandaoserver"); //把guandaoserver去掉就是匿名,就不能跨进程了。 if (mutex == NULL) {//创建 mutex = CreateMutexA(NULL, TRUE, "guandaoserver"); //如果是匿名就不能发挥作用了 } else { MessageBoxA(0, "only one", "only one", 0); exit(0); //exit(0)表示正常退出,exit(x)都表示异常退出. } } //mutex是内核所有的进程都能读到,限定程序只能打开一次。 void main() { test(); start(); printf("服务器启动 "); system("pause"); write(); system("pause"); read(); system("pause"); }
- 客户端
#include <stdio.h> #include <Windows.h> #define SIZE 4096 char pipename[128] = "\\.\Pipe\guandaopipe"; //用这种模式命名等同于设备。 HANDLE m_pipe = NULL; //管道的句柄 void read() { char buf[SIZE] = { 0 }; //我们有可能把管道的所有信息都读了,初始化时原则上初始为0。 int last = 0; if (!ReadFile(m_pipe, buf, SIZE, &last, NULL)) //Readpipe是纯C语言里边,如果是C的管道库,用Readpipe,C语言把所有的设备当成文件来处理,所以用ReadFile,若返回值是0表示读取失败. { printf("读取失败"); return; } printf(" read%s", buf); } void write() { char str[128] = "又丑又傻多看书。"; int last = 0; BOOL res = WriteFile(m_pipe, str, sizeof(str), &last, NULL); if (!res) { printf("写入失败"); } } void main() { //NMPWAIT_WAIT_FOREVER 常用到无限等待,表示如果没有管道就一直卡着 if (!WaitNamedPipeA(pipename, NMPWAIT_USE_DEFAULT_WAIT)) //NMPWAIT_USE_DEFAULT_WAIT表示一般等待,只等一下 { MessageBoxA(0, "connected NO", "connected NO", 0); return; } m_pipe = CreateFileA(pipename, //名称 GENERIC_WRITE | GENERIC_READ, //既能读又能写,是通过位运算符实现的。 1, //表示是否共享,1表示独有,0表示共有 NULL, //默认安全属性 OPEN_EXISTING, //打开已经存在的 FILE_ATTRIBUTE_NORMAL,//这两个表示两个默认的属性 NULL ); system("pause"); read(); system("pause"); write(); system("pause"); }