网络版sendmessage(跨进程消息处理demo)

本文档展示了如何实现一个本地和网络消息处理的C语言库,包括消息注册、注销、发送和删除功能。此外,还包含了网络通信部分的代码,用于处理TCP服务器和客户端的连接、数据发送与接收。测试工程分别提供了服务端和客户端的示例,实现了进程间的消息传递。
摘要由CSDN通过智能技术生成

一工程分布

1、消息处理工程

消息处理动态库工程

1、本地和网络消息处理

动态库接口定义
bylhMessage.h

#include "dllBase.h"

#ifndef BYLH_MESSAGE_H
#define BYLH_MESSAGE_H

#define MSG_LEN (32)

typedef void(*MSG_HANDLER)( const char* strCmd, void* arg1, void* arg2 );
BYLH_MESSAGE_DLL msg_state  BylhMsgModelInit(int i);//!< i 0:服务端  1:客户端
BYLH_MESSAGE_DLL msg_state  BylhRegMsg(const char msg[MSG_LEN], MSG_HANDLER onCommand);
BYLH_MESSAGE_DLL msg_state  BylhUnRegMsg(const char  msg[MSG_LEN], MSG_HANDLER onCommand);
BYLH_MESSAGE_DLL msg_state  BylhSendMsg(const char msg[MSG_LEN], void * arg1, unsigned int arg1Len, void* arg2, unsigned int arg2Len);


#endif // !BYLH_MESSAGE_H
';

dllBase.h

#pragma once

#ifdef __cplusplus
#define BYLH_MESSAGE_DLL extern "C" 
#else
#ifdef DLL_EXPORT
#define BYLH_MESSAGE_DLL __declspec(dllexport)
#else
#define BYLH_MESSAGE_DLL __declspec(dllimport)
#endif
#endif // !__cplusplus

typedef enum
{
	msg_state_ok,
	msg_state_failed,
	msg_state_para_error,
	msg_state_invalid_handle,
	msg_state_unknow_error,
}msg_state;

typedef enum 
{
	TEST_CMD
}CMD_EN;

typedef struct Link{
	void*  elem;
	struct Link *next;
	int cnt;
}link;
link * initLink();
void destroyLink(link * p);
link * appendElem(link * p, void * pData);
int delElem(link * p, void * pData);
void * pop(link * p);
int linkSize(link * p);

bylhMessage.c部分实现


#pragma pack(push)
#pragma pack(1)
typedef struct  
{
	char msg[MSG_LEN];
	link * funcLink;
	char lock;//!< 锁   线程互斥
}BylhMsgMap;
typedef struct __MsgData
{
	char msg[MSG_LEN];
	char arg1[1024];
	unsigned int arg1Len;
	char arg2[1024];
	unsigned int arg2Len;
}MsgData;
#pragma pack(pop)
static link * g_msgMapLink = NULL;
static net_hd g_msgSerHd = NULL;
static net_hd g_msgClientHd = NULL;
static int g_runningMode = 0;
void etnMsgCallBack(void *pData, unsigned int dataLen)
{
	if (dataLen != sizeof( MsgData ))
		return;
	struct __MsgData * pMsgData = ( MsgData * )pData;
	BylhMsgDel(pMsgData->msg, pMsgData->arg1, pMsgData->arg2);
	//BylhSendMsg(pMsgData->msg, pMsgData->arg1, pMsgData->arg1Len, pMsgData->arg2, pMsgData->arg2Len);
}
BYLH_MESSAGE_DLL msg_state BylhMsgModelInit(int i)
{
	if (i == 0)//!< 服务端
	{
		g_runningMode = 0;
		if (NULL == g_msgSerHd)
			g_msgSerHd = creatTcpServer(6514, etnMsgCallBack);
		return msg_state_ok;
	}
	else//!< 客户端
	{
		g_runningMode = 1;
		if (NULL == g_msgSerHd)
			g_msgSerHd = creatTcpClient("127.0.0.1", 6514, etnMsgCallBack);
		return msg_state_ok;
	}
	return msg_state_failed;
}

BYLH_MESSAGE_DLL msg_state  BylhRegMsg(const char msg[MSG_LEN], MSG_HANDLER onCommand)
{
	if (msg == NULL || onCommand == NULL || strlen(msg) == 0)
		return msg_state_para_error;
	if (g_msgMapLink == NULL)
	{
		g_msgMapLink = initLink();
		if (g_msgMapLink == NULL)
			return msg_state_failed;
	}
	link* temp = g_msgMapLink;
	while (temp->next)
	{
		temp = temp->next;
		if (strcmp(( ( BylhMsgMap  * )( temp->elem ) )->msg, msg) == 0)
		{
			//!< 防止重复注册
			//......
			//!< 注册
			while (( ( BylhMsgMap  * )( temp->elem ) )->lock == 1);
			( ( BylhMsgMap  * )( temp->elem ) )->lock = 1;
			appendElem(( ( BylhMsgMap  * )( temp->elem ) )->funcLink, onCommand);
			( ( BylhMsgMap  * )( temp->elem ) )->lock = 0;
			return msg_state_ok;
		}
	}
	BylhMsgMap * pNewMsg = ( BylhMsgMap * )malloc(sizeof( BylhMsgMap ));
	memset(pNewMsg, 0x0, sizeof( BylhMsgMap ));
	strcpy_s(pNewMsg->msg, MSG_LEN, msg);
	pNewMsg->funcLink = initLink();
	pNewMsg->lock = 0;
	appendElem(pNewMsg->funcLink, onCommand);
	appendElem(g_msgMapLink, pNewMsg);
	return msg_state_ok;
}

BYLH_MESSAGE_DLL msg_state   BylhUnRegMsg(const char msg[MSG_LEN], MSG_HANDLER onCommand)
{
	if (msg == NULL || onCommand == NULL || strlen(msg) == 0)
		return msg_state_para_error;
	if (g_msgMapLink == NULL)
	{
		g_msgMapLink = initLink();
		if (g_msgMapLink == NULL)
			return msg_state_failed;
	}
	link* temp = g_msgMapLink;
	while (temp->next)
	{
		temp = temp->next;
		if (strcmp(( ( BylhMsgMap  * )( temp->elem ) )->msg, msg) == 0)
		{
			while (( ( BylhMsgMap  * )( temp->elem ) )->lock == 1);
			( ( BylhMsgMap  * )( temp->elem ) )->lock = 1;
			delElem(( ( BylhMsgMap  * )( temp->elem ) )->funcLink, onCommand);
			( ( BylhMsgMap  * )( temp->elem ) )->lock = 0;
			return msg_state_ok;
		}
	}
	return msg_state_failed;
}

 msg_state  BylhMsgDel(const char msg[MSG_LEN], void * arg1, void* arg2)
{
	if (msg == NULL || strlen(msg) == 0)
		return msg_state_para_error;
	if (g_msgMapLink == NULL)
	{
		g_msgMapLink = initLink();
		if (g_msgMapLink == NULL)
			return msg_state_failed;
	}
	link* temp = g_msgMapLink;
	while (temp->next)
	{
		temp = temp->next;
		if (strcmp(( ( BylhMsgMap  * )( temp->elem ) )->msg, msg) == 0)
		{

			link* temp2 = ( ( BylhMsgMap  * )( temp->elem ) )->funcLink;
			while (( ( BylhMsgMap  * )( temp->elem ) )->lock == 1);
			( ( BylhMsgMap  * )( temp->elem ) )->lock = 1;
			while (temp2->next)
			{
				temp2 = temp2->next;
				MSG_HANDLER func = ( MSG_HANDLER )( temp2->elem );
				func(msg, arg1, arg2);
			}
			( ( BylhMsgMap  * )( temp->elem ) )->lock = 0;
			return msg_state_ok;
		}
	}
	return msg_state_failed;
}

 BYLH_MESSAGE_DLL msg_state  BylhSendMsg(const char msg[MSG_LEN], void * arg1, unsigned int arg1Len, void* arg2, unsigned int arg2Len)
{
	MsgData * pMsgData = ( MsgData * )malloc(sizeof( MsgData ));
	memset(pMsgData, 0x0, sizeof( MsgData ));
	memcpy(pMsgData->msg, msg, strlen(msg));
	memcpy(pMsgData->arg1, arg1, arg1Len);
	memcpy(pMsgData->arg2, arg2, arg2Len);
	pMsgData->arg1Len = arg1Len;
	pMsgData->arg2Len = arg2Len;
	if (g_runningMode == 0)
	{
		serverSocketSendData(g_msgSerHd, TEST_CMD, sizeof( MsgData ), pMsgData);
	}
	else
	{
		clientSocketSendData(g_msgSerHd, TEST_CMD, sizeof( MsgData ), pMsgData);
	}
	return BylhMsgDel(msg, arg1, arg2);
}

下面是网络部分的处理
netCtl.h

#pragma once
#include "dllBase.h"

#ifndef net_hd
#define  net_hd void*
#endif // !net_hd

typedef void(*ethDataCallBack)( void *pData, unsigned int dataLen );

net_hd creatTcpServer(const int port, ethDataCallBack dataCallBack);
net_hd creatTcpClient(const char * serverIp, const int serverPort, ethDataCallBack dataCallBack);
int clientSocketSendData(net_hd netHd, CMD_EN funEn, unsigned int dataLen, void * dataSrc);
int serverSocketSendData(net_hd netHd, CMD_EN funEn, unsigned int dataLen, void * dataSrc);

netCtl.c

#include "netCtl.h"
#include <stdio.h>
#include<Winsock2.h>
#include<time.h>
#include<string.h>
#include <ws2def.h>
#pragma warning(disable:4996)
#pragma comment(lib,"ws2_32.lib")
#pragma pack(push)
#pragma pack(1)
typedef struct __netHandle{
	SOCKET sk;
	struct sockaddr_in  sa;
	BOOL threadDone;
	link * msgLink;
	link * clientSocketLink;
	net_hd serverHd;
	ethDataCallBack dataRcevCallback;
}netHandle;

typedef struct
{
	unsigned int headerHead;//!< 0x55AAAA55
	CMD_EN funEn;
	unsigned int frameTotleLen;
	unsigned int dataLen;
	void * pData;
}socketFrame;
#pragma pack(pop)

BOOL socketSend(SOCKET sk, unsigned int dataLen, void * dataSrc)
{
#if 0
	puts("recv:");
	for (unsigned int i = 0; i < dataLen; i++)
	{
		printf("%02x ", ( ( char* )dataSrc )[i]);
		if (i % 16 == 0)
			puts("");
	}
	puts("");
#endif
	unsigned int curSend = 0;
	while (curSend < dataLen)
	{
		int n = send(sk, ( ( char* )dataSrc ) + curSend, dataLen - curSend,0);
		if (n <= 0)
			return FALSE;
		curSend += n;
	}
	return TRUE;
}

DWORD WINAPI tcpNewConnectProc(LPVOID p)
{
	netHandle * pNewConnectNetHandle = ( netHandle * )p;
	char * recvData = ( char * )malloc(3 * 1024 * 1024);
	int ret;
	while (pNewConnectNetHandle->threadDone == FALSE)
	{
		memset(recvData, 0x0, 3 * 1024 * 1024);
		ret = recv(pNewConnectNetHandle->sk, recvData, 3*1024*1024, 0);
		if (ret <= 0)
		{
			puts("client disconnect!");
			pNewConnectNetHandle->threadDone = TRUE;
			break;
			continue;
		}
#if 0
		puts("recv:");
		for (int i = 0; i < ret; i++)
		{
			printf("%02x ", ( ( char* )recvData )[i]);
			if (i % 16 == 0)
				puts("");
		}
		puts("");
#endif
		socketFrame * pSocketFrame = ( socketFrame * )recvData;
		if (pSocketFrame->headerHead == 0x55AAAA55)
		{
			char * dataSrc = ( char* )malloc(pSocketFrame->dataLen);
			memcpy(dataSrc, (char*)recvData + sizeof( socketFrame ), pSocketFrame->dataLen);
			if (pNewConnectNetHandle->dataRcevCallback)
			{
				pNewConnectNetHandle->dataRcevCallback(dataSrc, pSocketFrame->dataLen);
			}
			free(dataSrc);
		}
// 		recvData[ret] = '\0';
// 		printf("%s\n", recvData);
// 		send(pNewConnectNetHandle->sk, recvData, strlen(recvData), 0);
	}
	netHandle * serverHd = pNewConnectNetHandle->serverHd;
	delElem(serverHd->clientSocketLink, pNewConnectNetHandle);
	free(pNewConnectNetHandle);
	free(recvData);
	return 0;
}
DWORD WINAPI dataSendProc(LPVOID p)//!< 数据发送线程
{
	unsigned char * sendBuf = ( unsigned char * )malloc(2 * 1024 * 1024);
	netHandle * pServerNetHandle = ( netHandle * )p;
	while (pServerNetHandle->threadDone == FALSE)
	{
		if (linkSize(pServerNetHandle->msgLink))
		{
			//!< todo  套接字分发数据
			if (linkSize(pServerNetHandle->clientSocketLink))
			{
				link * msgRes = pop(pServerNetHandle->msgLink);
				link * skRes = pServerNetHandle->clientSocketLink->next;
				while (msgRes&&msgRes->elem)
				{
					socketFrame * pSocketFrame = ( socketFrame * )msgRes->elem;
					memset(sendBuf, 0x0, 2 * 1024 * 1024);
					memcpy(sendBuf, pSocketFrame, sizeof( socketFrame ));
					memcpy(sendBuf + sizeof( socketFrame ), pSocketFrame->pData, pSocketFrame->dataLen);
					while (skRes&&skRes->elem)
					{
						netHandle* clientSk = ( netHandle* )skRes->elem;
						if (FALSE == socketSend(clientSk->sk, pSocketFrame->frameTotleLen, sendBuf))
						{
							perror("socket send err!");
							return GetLastError();
						}
						skRes = skRes->next;
					}
					free(pSocketFrame->pData);//!< 释放消息内容缓存区
					free(pSocketFrame);//!< 释放消息帧结构缓存区
					msgRes = pop(pServerNetHandle->msgLink);
				}
			}
			
		}
	}
	free(sendBuf);
	return 0;
}


DWORD WINAPI tcpListenProc(LPVOID p)
{
	netHandle * pNetHandle = ( netHandle * )p;
	struct sockaddr_in c_sin;
	int c_sin_len = sizeof( c_sin );
	while (FALSE == pNetHandle->threadDone)
	{
		printf("waiting for connect\n");
		netHandle * pClientNetHandle = ( netHandle* )malloc(sizeof( netHandle ) );
		memset(pClientNetHandle, 0x0, sizeof( netHandle ));
		pClientNetHandle->sk = accept(pNetHandle->sk, ( SOCKADDR * )&pClientNetHandle->sa, &c_sin_len);
		if (pClientNetHandle->sk == INVALID_SOCKET)
			printf("accept() Failed:%d\n", WSAGetLastError());
		else
		{
			pClientNetHandle->serverHd = pNetHandle;
			pClientNetHandle->dataRcevCallback = pNetHandle->dataRcevCallback;
			HANDLE hThread;
			DWORD  threadId;
			appendElem(pNetHandle->clientSocketLink, pClientNetHandle);
			hThread = CreateThread(NULL, 0, tcpNewConnectProc, pClientNetHandle, 0, &threadId); // 创建线程
		}
	}
	return 0;
}

net_hd creatTcpServer(const int port, ethDataCallBack dataCallBack)
{
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		return NULL;
	}
	SOCKET socket_of_server;
	socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_of_server == INVALID_SOCKET)
	{
		printf("socket() Failed:%d\n", WSAGetLastError());
		return NULL;
	}
	struct sockaddr_in s_sin;
	s_sin.sin_family = AF_INET;
	s_sin.sin_port = htons(port);
	s_sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	if (bind(socket_of_server, ( LPSOCKADDR )&s_sin, sizeof( s_sin )) == SOCKET_ERROR)
	{
		printf("blind() Failed:%d\n", WSAGetLastError());
		return NULL;
	}
	if (listen(socket_of_server, 5) == SOCKET_ERROR)
	{
		printf("listen() Failed:%d\n", WSAGetLastError());
		return NULL;
	}
	netHandle * pNetHandle = ( netHandle * )malloc(sizeof( netHandle ));
	memset(pNetHandle, 0x0, sizeof( netHandle ));
	pNetHandle->sk = socket_of_server;
	pNetHandle->msgLink = initLink();//!< 创建消息队列
	pNetHandle->clientSocketLink = initLink();//!< 创建套接字队列
	pNetHandle->dataRcevCallback = dataCallBack;
	HANDLE hThread;
	DWORD  threadId;

	hThread = CreateThread(NULL, 0, dataSendProc, pNetHandle, 0, &threadId); // 创建数据发送线程
	hThread = CreateThread(NULL, 0, tcpListenProc, pNetHandle, 0, &threadId); // 创建监听线程

	return pNetHandle;
}
void destroyTcpServer(net_hd netHd)
{
	netHandle * pNetHandle = ( netHandle * )netHd;
	closesocket(pNetHandle->sk);
	WSACleanup();
	pNetHandle->threadDone = TRUE;//!< 控制进程退出
	destroyLink(pNetHandle->clientSocketLink);
	destroyLink(pNetHandle->msgLink);
	free(pNetHandle);
}
net_hd creatTcpClient(const char * serverIp, const int serverPort, ethDataCallBack dataCallBack)
{
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		return NULL;
	}
	SOCKET socket_client = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_client == INVALID_SOCKET)
	{
		perror(" Failed socket() \n");
		return NULL;
	}
	struct sockaddr_in server_in;
	server_in.sin_family = AF_INET;
	server_in.sin_port = htons(serverPort);
	server_in.sin_addr.S_un.S_addr = inet_addr(serverIp);

	if (connect(socket_client, ( struct sockaddr* )&server_in, sizeof( server_in )) == -1)
	{
		perror(" Failed connect() \n");
		return NULL;
	}
	else
	{
		printf("connect %s.%d\n", inet_ntoa(server_in.sin_addr), server_in.sin_port);
	}
	netHandle * pNetHandle = ( netHandle * )malloc(sizeof( netHandle ));
	netHandle * pNetHandleTmp = ( netHandle * )malloc(sizeof( netHandle ));
	memset(pNetHandle, 0x0, sizeof( netHandle ));
	pNetHandle->sk = socket_client;
	memcpy(pNetHandleTmp, pNetHandle, sizeof( netHandle ));
	pNetHandle->sa = server_in;
	pNetHandle->msgLink = initLink();
	pNetHandle->clientSocketLink = initLink();
	pNetHandle->dataRcevCallback = dataCallBack;
	appendElem(pNetHandle->clientSocketLink, pNetHandleTmp);
	HANDLE hThread;
	DWORD  threadId;

	hThread = CreateThread(NULL, 0, tcpNewConnectProc, pNetHandle, 0, &threadId); // 创建数据接收线程
	hThread = CreateThread(NULL, 0, dataSendProc, pNetHandle, 0, &threadId); // 创建数据发送线程

	return NULL;
}


int serverSocketSendData(net_hd netHd, CMD_EN funEn, unsigned int dataLen, void * dataSrc)
{
	if (NULL == netHd)
		return -1;
	struct __netHandle * pNetHandle = ( netHandle * )netHd;
	socketFrame * pSocketFrame = ( socketFrame * )malloc(sizeof( socketFrame ));
	pSocketFrame->headerHead = 0x55AAAA55;
	pSocketFrame->frameTotleLen = dataLen + sizeof( socketFrame );
	pSocketFrame->funEn = funEn;
	pSocketFrame->dataLen = dataLen;
	pSocketFrame->pData = malloc(dataLen);
	memset(pSocketFrame->pData, 0x0, dataLen);
	memcpy(pSocketFrame->pData, dataSrc, dataLen);
	return NULL == appendElem(pNetHandle->msgLink, pSocketFrame) ? -1 : 0;
}
int clientSocketSendData(net_hd netHd, CMD_EN funEn, unsigned int dataLen, void * dataSrc)
{
	return serverSocketSendData(netHd, funEn, dataLen, dataSrc);
}

2、测试工程(服务端)

服务端

3、测试工程(客户端)

客户端
测试效果
测试

模块主要处理同进程模块间和进程间的带参消息处理。无需句柄,模块自主注册监听消息类型。
比如 在本地和远端都注册了消息“ABCD”,那么当某个模块发送此消息,则远端和本地都会收到此消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值