共享通信.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;
}