ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

VC++命名管道通信(自动重置事件对象)

2021-11-17 18:31:23  阅读:118  来源: 互联网

标签:include cout 重置 NamePipe C++ 管道 cEvent NULL buf


服务端:
头文件:

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include <string>
#include <cstring>
#include <iostream>
#include <process.h>


using namespace std;


class NamePipe{

public:
	NamePipe(){

	}
	~NamePipe(){
		if (hPipe){
			CloseHandle(hPipe);
		}
	}

	void onPipeCreate();
	static DWORD WINAPI onPipeRead(LPVOID lpParameter);
	//void onPipeRead();
	//static DWORD WINAPI onPipeWrite(LPVOID lpParameter);
	void onPipeWrite();

	static HANDLE hPipe;
	static HANDLE hReadThread;
};

// TODO:  在此处引用程序需要的其他头文件

.cpp:

// NamePipe.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


HANDLE NamePipe::hPipe = NULL;
HANDLE NamePipe::hReadThread = NULL;
HANDLE cEvent = NULL;
BOOL fStop = FALSE;

//创建管道
void NamePipe::onPipeCreate(){
	//创建有名管道
	hPipe = CreateNamedPipe(_T("\\\\.\\pipe\\new_namedpipe"), PIPE_ACCESS_DUPLEX, 0, 1, 1024, 1024, 0, NULL);
	if (INVALID_HANDLE_VALUE == hPipe){
		cout << "创建命名管道失败!" << endl;
		CloseHandle(hPipe);
		hPipe = NULL;
		return;
	}
	else{
		cout << "创建命名管道成功!" << endl;
	}


	//创建匿名的人工重置事件对象
	HANDLE hEvent;
	hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (!hEvent){
		cout << "创建事件对象失败!" << endl;
		CloseHandle(hPipe);
		hPipe = NULL;
		return;
	}
	else{
		cout << "创建事件对象成功!" << endl;
	}


	//异步输入输出的结构体
	OVERLAPPED ov;
	ZeroMemory(&ov, sizeof(OVERLAPPED));
	ov.hEvent = hEvent;

	//等待客户端请求
	if (!ConnectNamedPipe(hPipe, &ov)){
		if (ERROR_IO_PENDING != GetLastError()){
			cout << "等待客户端连接失败!" << endl;
			CloseHandle(hPipe);
			CloseHandle(hEvent);
			hPipe = NULL;
			return;
		}
	}


	//等待事件对象变为有信号状态
	if (WAIT_FAILED == WaitForSingleObject(hEvent, INFINITE)){
		cout << "等待对象失败!" << endl;
		CloseHandle(hPipe);
		CloseHandle(hEvent);
		hPipe = NULL;
		return;
	}
	else{
		cout << "对象变为有信号状态!" << endl;
	}

	CloseHandle(hEvent);
	return;
}





//线程读取数据
DWORD WINAPI NamePipe::onPipeRead(LPVOID lpParameter){

	char buf[1000]{0};
	char *data[1000]{0};
	char pid[20]{0};
	char *buf2 = NULL;
	DWORD dwRead;

	while (1)
	{
		//将自动重置对象设为无信号状态
		WaitForSingleObject(cEvent, INFINITE);
		ResetEvent(cEvent);

		ZeroMemory(buf, sizeof(buf));
		ZeroMemory(data, sizeof(data));
		ZeroMemory(pid, sizeof(pid));

		//读取数据
		if (!ReadFile(hPipe, buf, 1000, &dwRead, NULL)){
			cout << "服务端读取失败" << endl;

			fStop = TRUE;
			SetEvent(cEvent);
			break;
		}
		else{
			buf2 = strtok(buf, "\n");
			strcpy(pid, buf2);

			int i = 0;
			while (buf2 != NULL)
			{
				buf2 = strtok(NULL, "\n");

				if (buf2 != NULL){
					data[i] = buf2;

					cout << "收到来自进程[" << pid << "]的数据:" << data[i] << endl;
					++i;
				}
			}
		}

		//将自动重置对象设为有信号状态
		SetEvent(cEvent);
	}

	return 0;
}







//写入数据
void NamePipe::onPipeWrite(){

	char buf[100] = "123";
	DWORD dwWrite;

	cout << "请输入要发送给客户端的信息:";
	ZeroMemory(buf, sizeof(buf));
	cin >> buf;

	//写入数据
	if (!WriteFile(hPipe, buf, strlen(buf) + 1, &dwWrite, NULL)){
		cout << "服务端写入失败" << endl;

		if (232 == GetLastError()){
			cout << "客户端断开连接" << endl;
			fStop = TRUE;
		}
	}
	else{
		cout << "服务端写入成功" << endl;
	}

	return;
}





int _tmain(int argc, _TCHAR* argv[])
{
	//创建并初始化管道
	NamePipe np;
	np.onPipeCreate();

	//创建读取线程
	NamePipe::hReadThread = CreateThread(NULL, 0, NamePipe::onPipeRead, NULL, 0, NULL);
	if (NULL == NamePipe::hReadThread){
		CloseHandle(NamePipe::hReadThread);
		return -1;
	}
	CloseHandle(NamePipe::hReadThread);

	//创建写入线程
	//NamePipe::hWriteThread = CreateThread(NULL, 0, NamePipe::onPipeWrite, NULL, 0, NULL);
	//if (NULL == NamePipe::hWriteThread){
	//	CloseHandle(NamePipe::hWriteThread);
	//	return -1;
	//}
	//CloseHandle(NamePipe::hWriteThread);


	//创建匿名自动重置事件对象
	cEvent = CreateEvent(NULL, FALSE, FALSE, 0);
	if (!cEvent){
		cout << "创建匿名自动重置事件对象失败" << endl;
		return -1;
	}
	SetEvent(cEvent);

	while (!fStop){
		//将自动重置对象设为无信号状态
		WaitForSingleObject(cEvent, INFINITE);
		ResetEvent(cEvent);

		np.onPipeWrite();

		//将自动重置对象设为有信号状态
		SetEvent(cEvent);
	}

	return 0;
}



//线程写入数据
//DWORD WINAPI NamePipe::onPipeWrite(LPVOID lpParameter){
//
//	char buf[100]{0};
//	DWORD dwWrite;
//
//	while (1)
//	{
//		ZeroMemory(buf, sizeof(buf));
//
//		cout << "请输入要发送给客户端的信息:";
//		cin >> buf;
//		if (!WriteFile(hPipe, buf, strlen(buf) + 1, &dwWrite, 0)){
//			cout << "server write failed" << endl;
//			break;
//		}
//
//		cout << "server write success" << endl;
//
//	}
//
//	return -1;
//}




客户端:
头文件:

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include <string>
#include <cstring>
#include <iostream>
#include <process.h>


using namespace std;


class NamePipe{

public:
	NamePipe(){

	}
	~NamePipe(){
		if (hPipe){
			CloseHandle(hPipe);
		}
	}

	void onPipeConnect();
	static DWORD WINAPI onPipeRead(LPVOID lpParameter);
	//static DWORD WINAPI onPipeWrite(LPVOID lpParameter);
	void onPipeWrite();

	static HANDLE hPipe;
	static HANDLE hReadThread;
};


// TODO:  在此处引用程序需要的其他头文件

.cpp:

// NamePipe2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


HANDLE NamePipe::hPipe = NULL;
HANDLE NamePipe::hReadThread = NULL;
HANDLE cEvent = NULL;
BOOL fStop = FALSE;


//连接服务器
void NamePipe::onPipeConnect(){
	//判断是否可用的有名管道
	if (!WaitNamedPipe(_T("\\\\.\\pipe\\new_namedpipe"), NMPWAIT_WAIT_FOREVER)){
		cout << "没有可用的管道" << endl;
		return;
	}
	else{
		cout << "找到可用管道" << endl;
	}
	//打开可用的有名管道,与服务器通信
	hPipe = CreateFile(_T("\\\\.\\pipe\\new_namedpipe"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == hPipe){
		cout << "打开有名管道失败" << endl;
		hPipe = NULL;
		return;
	}
	else{
		cout << "打开有名管道成功" << endl;
	}

}


//线程读取数据
DWORD WINAPI NamePipe::onPipeRead(LPVOID lpParameter){

	char buf[100]{0};
	DWORD dwRead;

	while (1)
	{
		//将自动重置对象设为无信号状态
		WaitForSingleObject(cEvent, INFINITE);
		ResetEvent(cEvent);

		if (ReadFile(hPipe, buf, 100, &dwRead, NULL)){
			cout << "客户端读取成功,收到来自服务端的数据:" << buf << endl;
		}
		else{
			if (ERROR_IO_PENDING == GetLastError()){
				cout << "管道被占用" << endl;
			}
			else if (ERROR_BROKEN_PIPE == GetLastError()){
				cout << "管道已断开" << endl;
			}
			else{
				cout << "客户端读取失败" << endl;
			}

			fStop = TRUE;
			SetEvent(cEvent);
			break;
		}

		//将自动重置对象设为有信号状态
		SetEvent(cEvent);
	}

	return 0;
}



//发送数据
void NamePipe::onPipeWrite(){

	char buf[1000]{0};
	char data[1000]{0};
	char pid[20]{0};

	DWORD MyPid;
	DWORD dwWrite;

	//清空数组
	ZeroMemory(buf, sizeof(buf));
	ZeroMemory(data, sizeof(data));
	ZeroMemory(pid, sizeof(pid));

	//打开文件,读取其中的内容
	HANDLE hFile = NULL;
	hFile = CreateFile(_T("F:\\Zyh\\vc++demo\\NamePipe4\\test.csv"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == hFile){
		cout << "打开文件失败" << endl;
		return;
	}
	else{
		DWORD dwRead;
		ZeroMemory(buf, sizeof(buf));
		if (!ReadFile(hFile, buf, sizeof(buf), &dwRead, 0)){
			cout << "读取文件失败" << endl;
			return;
		}
		else{
			CloseHandle(hFile);
		}
	}

	//获取当前进程号
	MyPid = getpid();
	_ultoa(MyPid, pid, 10);

	//拼接进程号和数据
	strcat(data, pid);
	strcat(data, "\n");
	strcat(data, buf);

	//写入数据
	if (!WriteFile(hPipe, data, strlen(data) + 1, &dwWrite, NULL)){
		cout << "客户端写入数据失败" << endl;
	}
	else{
		cout << "客户端写入数据成功" << endl;
	}

	return;
}



int _tmain(int argc, _TCHAR* argv[])
{
	//初始化并连接管道
	NamePipe np;
	np.onPipeConnect();

	//创建读取线程
	NamePipe::hReadThread = CreateThread(NULL, 0, NamePipe::onPipeRead, NULL, 0, NULL);
	if (NULL == NamePipe::hReadThread){
		CloseHandle(NamePipe::hReadThread);
		return -1;
	}
	CloseHandle(NamePipe::hReadThread);

	//创建写入线程
	//NamePipe::hWriteThread = CreateThread(NULL, 0, NamePipe::onPipeWrite, NULL, 0, NULL);
	//if (NULL == NamePipe::hWriteThread){
	//	CloseHandle(NamePipe::hWriteThread);
	//	return -1;
	//}


	//创建匿名自动重置事件对象
	cEvent = CreateEvent(NULL, FALSE, FALSE, 0);
	if (!cEvent){
		cout << "创建匿名自动重置事件对象失败" << endl;
		return -1;
	}
	SetEvent(cEvent);

	while (!fStop){
		//将自动重置对象设为无信号状态
		WaitForSingleObject(cEvent, INFINITE);
		ResetEvent(cEvent);

		np.onPipeWrite();

		//将自动重置对象设为有信号状态
		SetEvent(cEvent);
	}

	system("pause");
	return 0;
}



//线程写入数据
//DWORD WINAPI NamePipe::onPipeWrite(LPVOID lpParameter){
//
//	char buf[100]{0};
//	char pid[20]{0};
//
//	DWORD MyPid;
//	DWORD dwWrite;
//
//	while (1)
//	{
//		ZeroMemory(buf, sizeof(buf));
//		ZeroMemory(pid, sizeof(pid));
//
//		MyPid = getpid();
//		_ultoa(MyPid, pid, 10);
//
//		cout << "请输入要发送给服务端的信息:";
//		cin >> buf;
//		strcat(buf, "@pid@");
//		strcat(buf, pid);
//
//		if (!WriteFile(hPipe, buf, strlen(buf) + 1, &dwWrite, 0)){
//			cout << "client write failed" << endl;
//			return -1;
//		}
//
//		cout << "client write success" << endl;
//	}
//}











标签:include,cout,重置,NamePipe,C++,管道,cEvent,NULL,buf
来源: https://blog.csdn.net/bangtanhui/article/details/121384684

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有