使用管道进行进程间通信-秋风

前言

  前面使用邮槽进行实现了进程间的通信,只不过邮槽通信是一个发送,一个接送.而且邮槽不是可靠的.这里使用管道实现进程通信的收发.

服务端 server.c

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define SIZE 4096
//管道名称   格式 以\\\\.\\Pipe\\管道名
char pipename[32] = "\\\\.\\Pipe\\pipe_server";
//管道句柄
HANDLE p_pipe = NULL;

void pipe_start()
{
	p_pipe = CreateNamedPipeA(
		pipename,                 //管道名称
		PIPE_ACCESS_DUPLEX,       //管道读写属性
		PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,  //消息模式,读模式,等待模式
		PIPE_UNLIMITED_INSTANCES, //最大个数
		SIZE,                     //输出缓冲区大小
		SIZE,                     //输入缓冲区大小
		0,                        //超时,无限等待
		NULL
	);
	if (p_pipe == NULL)
	{
		printf("创建管道失败!\n");
	}
	//是否连接上管道
	BOOL isConnect = ConnectNamedPipe(p_pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
	if (isConnect)
	{
		printf("连接完成!\n");
	}
	else
	{
		printf("管道连接失败!\n");
	}
}

//读取
void read()
{
	char buf[SIZE] = { 0 };
	int last = 0;

	//ReadFile
	//第一个参数句柄
	//第二个字符指针
	//第三个字符大小
	//第四个实际读取的字符数量
	//第五个异步读取操作使用,这是不使用
	if (!ReadFile(p_pipe, buf, SIZE, &last, NULL))
	{
		printf("读取失败!\n");
	}
	else
	{
		buf[last] = '\0';
		printf("服务器读取= %s\n", buf);
	}
}

//写入
void write()
{
	char str[128] = "hello";
	int writeCount = 0;
	//WriteFile
	//第一个参数句柄
	//第二个字符指针
	//第三个字符大小
	//第四个实际写入的字符数量
	BOOL result = WriteFile(p_pipe, str, strlen(str) + 1, &writeCount, NULL);
	if (!result)
	{
		printf("写入失败!\n");
		return;
	}
	printf("服务器写入=%s\n", str);
}

//通过互斥体,实现进程唯一
void test()
{
	HANDLE mutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, "pipe_server");
	if (mutex == NULL)
	{
		mutex = CreateMutexA(NULL, TRUE, "pipe_server");
	}
	else
	{
		MessageBoxA(0, "only one", "only on", 0);
		exit(0);
	}
}

int main(int argc, char *argv[])
{
	test();
	pipe_start();
	printf("管道启动..\n");

	write();

	read();

	system("pause");
	return 0;
}

客户端 client.c

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define SIZE 4096
//管道名称格式 以\\\\.\\Pipe\\管道名
char pipename[32] = "\\\\.\\Pipe\\pipe_server";
//管道句柄
HANDLE p_pipe = NULL;

//读取
void pipe_read()
{
	char buf[SIZE] = { 0 };
	int readCount = 0;
	if (!ReadFile(p_pipe, buf, SIZE, &readCount, NULL))
	{
		printf("读取失败!\n");
		return;
	}
	else
	{
		buf[readCount] = '\0';
		printf("客户端读取= %s\n", buf);
	}
}

//写入
void pipe_write()
{
	char str[128] = "word";
	int writeCount = 0;
	BOOL result = WriteFile(p_pipe, str, strlen(str) + 1, &writeCount,NULL);
	if (!result)
	{
		printf("写入失败!\n");
		return;
	}
	printf("客户端写入=%s\n", str);
}

int main()
{
	if (!WaitNamedPipeA(pipename, NMPWAIT_USE_DEFAULT_WAIT))
	{
		printf("没有连接上!\n");
		return 0;
	}
	p_pipe = CreateFileA(pipename,                        //管道名称
			     GENERIC_READ | GENERIC_WRITE,    //读写
			     1,				      //共享属性  0是共享 1是独占                                          
			     NULL,                            //默认安全属性
			     OPEN_EXISTING,                   //打开已经存在
			     FILE_ATTRIBUTE_NORMAL,
			     NULL);
	pipe_read();
	pipe_write();

	system("pause");
	return 0;
}

注意事项

  1. 先生成服务端server.c,在服务端test方法中,用互斥体来校验是否已经在进程中存在.
秋风 2016-07-24