一工程分布
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”,那么当某个模块发送此消息,则远端和本地都会收到此消息。