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

服务端:
头文件:

// 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;
//	}
//}











上一篇:mystat


下一篇:C(练习)