一种Win32进程间相互通信的尝试

这段代码展示了在Windows环境下,通过共享内存和信号量实现进程间通信的过程。主要包含初始化、发送数据、接收数据和销毁通信结构等操作。通信过程中涉及回调函数处理接收到的消息,并在服务端和客户端之间切换角色。
摘要由CSDN通过智能技术生成

共享通信.h

#pragma once
#include<iostream>
//#include<vector>
#include <windows.h>
//using namespace std;
typedef DWORD(*共享通信_回调)(PVOID hWrite, const char* msg, DWORD nLen, PVOID lparam);
#define MEMLEN 2048
#define MEMDATALEN MEMLEN - 12
struct stMemData {
	DWORD nLen;
	struct stMemData* next;
	BYTE data[MEMDATALEN];
};

struct stMsg {
	DWORD status;
	DWORD nLen;
	time_t 超时;
	BYTE data[MEMDATALEN];
};
typedef struct SHAREMEM {
	bool isServer;
	HANDLE hFileMapping;
	HANDLE 服务端;
	HANDLE 客户端;

	HANDLE 消息送达信号;
	stMsg* 传送媒介_读;
	stMsg* 传送媒介_写;
	HANDLE hThread;
	共享通信_回调 callback;
	PVOID lparam;

	BOOL is待发送消息;
	BOOL is等待响应;
	BOOL is消息已送达;

	struct stMemData* node_start;
	struct stMemData* node_end;
}*PSHAREMEM;

#define 共享通信_写入数据(addr,lpData,len) memcpy((char*)addr, lpData, nLen);
//static vector<string> g_msgArr;
static void shareMemThreadProc(PSHAREMEM sm) {
	HANDLE tmp;
	DWORD nlen = 0;
	while (true) {//INFINITE
		if (WaitForSingleObject(sm->服务端, 100) == WAIT_OBJECT_0) {
			ResetEvent(sm->服务端);
			DWORD status = sm->传送媒介_读->status;
			if (status == 0) {//收到客户端消息
				if (sm->传送媒介_读->nLen > 0) {
					//g_msgArr.push_back(string((char*)(sm->传送媒介_读->data)));
					struct stMemData* node = (struct stMemData*)malloc(sizeof(struct stMemData));
					node->nLen = sm->传送媒介_读->nLen;
					memcpy(node->data, sm->传送媒介_读->data, node->nLen);
					node->next = NULL;
					if (sm->node_end){
						sm->node_end->next = node;
						sm->node_end = node;
					}else {
						sm->node_start = node;
						sm->node_end = node;
					}
					printf("消息已收到:%s\n", (char*)(sm->传送媒介_读->data));
				}
				sm->传送媒介_读->status = 1;//反馈已收到
			}
			else  if (status == 100) {服务端退出 变更客户端为服务端
				printf("服务端已退出\n");
				tmp = sm->服务端;
				sm->服务端 = sm->客户端;
				sm->客户端 = tmp;

				stMsg* tt = sm->传送媒介_写;
				sm->传送媒介_写 = sm->传送媒介_读;
				sm->传送媒介_读 = tt;
				sm->isServer = true;
				continue;
			}
		}
		if (sm->is待发送消息) {//发送消息到服务端
			sm->is待发送消息 = false;
			sm->is等待响应 = true;
			sm->传送媒介_写->status = 0;
			sm->传送媒介_写->超时 = time(NULL) + 8000;
			printf("发送消息 %s\n", (char*)(sm->传送媒介_写->data));
			SetEvent(sm->客户端);
		}
		else {
			if (sm->is等待响应) {
				if (sm->传送媒介_写->status == 1) {//发送的消息成功接收
					printf("消息已送达 \n");
					sm->is等待响应 = false;
					sm->is消息已送达 = true;
					ReleaseSemaphore(sm->消息送达信号, 1, NULL);
				}
				else if (time(NULL) > sm->传送媒介_写->超时) {
					sm->is等待响应 = false;
					sm->is消息已送达 = false;
					ReleaseSemaphore(sm->消息送达信号, 1, NULL);
				}
				continue;
			}
			//printf("g_msgArr元素个数 %d\n", g_msgArr.size());
			/*if (!g_msgArr.empty()) {
				auto& item = g_msgArr.front();*/
			if (sm->node_start) {
				auto item = sm->node_start;
				sm->node_start = item->next;
				if (!sm->node_start)sm->node_end = NULL;
				if (sm->callback) {
					//nlen = sm->callback(sm->传送媒介_写->data, item.c_str(), item.size() + 1, sm->lparam);
					nlen = sm->callback(sm->传送媒介_写->data, (char*)item->data, item->nLen, sm->lparam);
					//g_msgArr.erase(g_msgArr.begin());
					free(item);
					if (nlen > 0) {
						//printf("处理消息:%s 返回%s\n", item.c_str(), (char*)sm->传送媒介_写->data);
						printf("处理消息:%s 返回%s\n", (char*)item->data, (char*)sm->传送媒介_写->data);
						sm->is等待响应 = true;
						sm->传送媒介_写->status = 0;
						sm->传送媒介_写->nLen = nlen;
						sm->传送媒介_写->超时 = time(NULL) + 8000;
						SetEvent(sm->客户端);
					}
					else {
						printf("callback 抛弃收到的消息%s\n", (char*)item->data);// item.c_str());
					}
				}
				else {

					printf("抛弃收到的消息%s\n", (char*)item->data);// item.c_str());
					//g_msgArr.erase(g_msgArr.begin());
					free(item);
				}
			}
		}
	}
}
static void 共享通信_销毁(PSHAREMEM sm) {
	if (sm) {
		if (sm->isServer == true) {
			sm->传送媒介_写->status = 100;
			SetEvent(sm->客户端);
			Sleep(300);
		}
		struct stMemData* node = sm->node_start;
		struct stMemData* tmp;
		while (node){
			tmp = node;
			node = node->next;
			free(tmp);
		}
		CloseHandle(sm->hThread);
		UnmapViewOfFile(sm->hFileMapping);
		CloseHandle(sm->客户端);
		CloseHandle(sm->服务端);
		CloseHandle(sm->消息送达信号);
		CloseHandle(sm->hFileMapping);
		free(sm);

		
	}
}
static bool 共享通信_发送数据(PSHAREMEM sm, PVOID lpData, UINT nLen) {
	if (lpData&& nLen) {
		if (nLen >= MEMDATALEN) {
			nLen = MEMDATALEN - 2;
		}
		sm->传送媒介_写->nLen = nLen;
		memcpy(sm->传送媒介_写->data, lpData, nLen);
		sm->传送媒介_写->data[nLen+1] = 0;
		sm->is待发送消息 = true;
		WaitForSingleObject(sm->消息送达信号, INFINITE);// == WAIT_OBJECT_0){
		return sm->is消息已送达;
	}
	return false;
}
static PSHAREMEM 共享通信_初始化(const char* txName, 共享通信_回调 callback, PVOID lparam) {
	char txNameBuffer[10];
	PVOID memAddr;
	PSHAREMEM sm = (PSHAREMEM)malloc(sizeof(struct SHAREMEM));
	wsprintfA(txNameBuffer, "S%s", txName);
	sm->hFileMapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, txName);
	if (sm->hFileMapping) { //客户端
		sm->isServer = false;
		memAddr = MapViewOfFile(sm->hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
		sm->传送媒介_读 = (stMsg*)memAddr;
		sm->客户端 = OpenEventA(EVENT_ALL_ACCESS, false, txNameBuffer);
		txNameBuffer[0] = 'C';
		sm->服务端 = OpenEventA(EVENT_ALL_ACCESS, false, txNameBuffer);
		sm->传送媒介_写 = (stMsg*)((char*)memAddr + MEMLEN);
		//printf("客户端 %p %p %d %d\n", sm->传送媒介_读, sm->传送媒介_写, sm->服务端, sm->客户端);
	}
	else {
		sm->hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, MEMLEN * 2, txName);
		if (sm->hFileMapping) {
			sm->isServer = true;

			memAddr = MapViewOfFile(sm->hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
			sm->传送媒介_写 = (stMsg*)memAddr;
			sm->传送媒介_读 = (stMsg*)((char*)memAddr + MEMLEN);
			sm->服务端 = CreateEventA(0, false, false, txNameBuffer);
			txNameBuffer[0] = 'C';
			sm->客户端 = CreateEventA(0, false, false, txNameBuffer);
			//printf("服务端 %p %p %d %d\n", sm->传送媒介_读, sm->传送媒介_写, sm->服务端, sm->客户端);
		}
	}
	sm->消息送达信号 = CreateSemaphoreA(NULL, 0, 5, NULL);
	sm->callback = callback;
	sm->lparam = lparam;
	sm->is待发送消息 = false;
	sm->is等待响应 = false;

	sm->node_start = NULL;
	sm->node_end = NULL;
	sm->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&shareMemThreadProc, sm, 0, NULL);
	return sm;
}

调用入口

#include <iostream>
#include "../共享通信.h"

DWORD 消息回调(PVOID hwrite,const char* msg, DWORD len,PVOID lparam) {
	//printf("收到消息:%s(%d)\n", msg, len);
	if (strcmp(msg,"666") == 0){
		len = strlen("999");
		memcpy(hwrite, "999", len);
		return len;
	}
	return 0;
}
int main(int argc, char** argv) {
	//dnsTest();
	//端口测试();

	auto pm=共享通信_初始化("tx", &消息回调,NULL);
	共享通信_发送数据(pm,(PVOID)"333",4);
	getchar();
	共享通信_销毁(pm);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值