管道通信初级

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");

}
原文地址:https://www.cnblogs.com/sjxbg/p/5946323.html