#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
//#define USE_SOCKET
#ifdef USE_SOCKET
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#endif
#if 1
#define DEBUG(fmt, arg...) printf("\033[32m[%s:%d]\033[36m"fmt"\033[0m\n", __FUNCTION__, __LINE__, ##arg)
#define DEBUG_ERR(fmt, arg...) printf("\033[32m[%s:%d]\033[31m"fmt"\033[0m\n", __FUNCTION__, __LINE__, ##arg)
#else
#define DEBUG(...)
#define DEBUG_ERR(...)
#endif
#ifndef USE_SOCKET
#define MSG_MAX_LEN (8192 - sizeof(long int))
typedef struct _msg_queue_st_
{
long int msg_type;
char msg[MSG_MAX_LEN];
}msg_queue_st;
#else
#define MASSAGE_QUEUE_NAME_SIZE 128
typedef struct _MSGQUE
{
int socket_id;
pthread_mutex_t msg_rwlock;
char name[MASSAGE_QUEUE_NAME_SIZE]; //for local socket name
unsigned short bind_port;
} MSGQUEUE;
static int s_socket_bind(int socket_handle, unsigned short bind_port)
{
int ret = -1;
if(socket_handle != -1)
{
struct sockaddr_in bind_sa;
memset(&bind_sa, 0, sizeof(struct sockaddr_in));
bind_sa.sin_family = AF_INET;
bind_sa.sin_addr.s_addr = htonl(INADDR_ANY);
bind_sa.sin_port = htons(bind_port);
ret = bind(socket_handle, (struct sockaddr *)&bind_sa, sizeof(struct sockaddr_in));
}
return ret;
}
static int s_socket_get_bind_port(int socket_handle)
{
unsigned short port = 0;
struct sockaddr_in bind_sa;
socklen_t sin_size = sizeof(struct sockaddr_in);
if(socket_handle == -1)
{
return port;
}
getsockname(socket_handle, (struct sockaddr*)&bind_sa, &sin_size);
port = ntohs(bind_sa.sin_port);
return port;
}
int s_socket_select(int sk, int flag, int to)
{
int iRet = -1;
if(sk != -1)
{
fd_set fds;
struct timeval tv;
struct timeval *ptv = (struct timeval*)0;
FD_ZERO(&fds);
FD_SET(sk, &fds);
if(-1 != to)
{
tv.tv_sec = to / 1000;
tv.tv_usec = (to % 1000) * 1000;
ptv = &tv;
}
iRet = select(sk + 1, ((flag & 1) ? &fds : 0), ((flag & 2) ? &fds : 0), ((flag & 4) ? &fds : 0), ptv);
if(iRet > 0)
{
iRet = FD_ISSET(sk,&fds) ? 1 : 0;
}
}
return iRet;
}
static int s_socket_sendto(int sk, unsigned char *buff, int len, int to, int iIpAddr, unsigned short usPort)
{
int iRet = 0;
struct sockaddr_in socket_sa;
socket_sa.sin_family = AF_INET;
socket_sa.sin_port = htons(usPort);
if(iIpAddr == 0)
{
socket_sa.sin_addr.s_addr = inet_addr("127.0.0.1");
}
else
{
socket_sa.sin_addr.s_addr = iIpAddr; //htonl(iIpAddr);
}
if(sk != -1 && buff && len > 0)
{
iRet = s_socket_select(sk, 2, to);
if(iRet > 0)
{
iRet = sendto(sk, (char*)buff, len, 0, (struct sockaddr *)&socket_sa, sizeof(socket_sa));
}
}
return iRet;
}
static int s_socket_recv(int sk, unsigned char *buff, int len, int to)
{
int iRet = 0;
if(sk != -1 && buff && len > 0)
{
iRet = s_socket_select(sk, 1, to);
if(iRet > 0)
{
iRet = recv(sk, (char*)buff, len, 0);
if(iRet <= 0)
{
iRet = -1;
}
}
}
return iRet;
}
#endif
int msg_queue_create(int *piMsgId)
{
#ifdef USE_SOCKET
int socket_id = -1;
char msg_queue_name[MASSAGE_QUEUE_NAME_SIZE];
int ret = -1;
socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socket_id == -1)
{
DEBUG_ERR("create socket failed.");
return -1;
}
snprintf(msg_queue_name, sizeof(msg_queue_name), "/dev/msg_queue%d", socket_id);
ret = s_socket_bind(socket_id, 0);
if(ret == -1)
{
close(socket_id);
DEBUG_ERR("blind socket failed.");
return -1;
}
MSGQUEUE* pMsgQueue = (MSGQUEUE*)malloc(sizeof(MSGQUEUE));
if(pMsgQueue == NULL)
{
close(socket_id);
DEBUG_ERR("malloc failed.");
return -1;
}
pthread_mutex_init(&pMsgQueue->msg_rwlock, NULL);
pMsgQueue->socket_id = socket_id;
pMsgQueue->bind_port = s_socket_get_bind_port(socket_id);
snprintf(pMsgQueue->name, sizeof(pMsgQueue->name), "%s", msg_queue_name);
*piMsgId = (int)pMsgQueue;
return 0;
#else
int iMsgId = 0;
iMsgId = msgget(IPC_PRIVATE, IPC_CREAT|IPC_EXCL|0666);
if(iMsgId < 0)
{
fprintf(stdout, "create msg error:errno=%d, err_msg=%s\n", errno, strerror(errno));
return -1;
}
if(piMsgId)
{
*piMsgId = iMsgId;
}
return 0;
#endif
}
int msg_queue_send(int iMsgId, void *pMsg, int iMsgSize)
{
#ifdef USE_SOCKET
MSGQUEUE * pMsgQueue = (MSGQUEUE *)iMsgId;
int iRet = -1;
if(!pMsgQueue || !pMsg || pMsgQueue->socket_id < 0)
{
return -1;
}
pthread_mutex_lock(&pMsgQueue->msg_rwlock);
iRet = s_socket_sendto(pMsgQueue->socket_id, (unsigned char *)pMsg, iMsgSize, 0, 0, pMsgQueue->bind_port);
pthread_mutex_unlock(&pMsgQueue->msg_rwlock);
if(iRet <= 0)
{
return -1;
}
return 0;
#else
int iRet = 0;
msg_queue_st msg;
if(iMsgSize <= 0)
{
fprintf(stdout, "message length is less than 0\n");
return -2;
}
memset(&msg, 0, sizeof(msg_queue_st));
memcpy(msg.msg, pMsg, iMsgSize);
msg.msg_type = iMsgId;
iRet = msgsnd(iMsgId, &msg, iMsgSize, 0);
if(iRet < 0)
{
fprintf(stdout, "send msg error:errno=%d, err_msg=%s\n", errno, strerror(errno));
return -1;
}
return 0;
#endif
}
#ifdef USE_SOCKET
static int s_msg_queue_receive(int hMsgQueueHandle, void *pvMessage, int msg_size, unsigned int uiTimeOutMs)
{
MSGQUEUE * pMsgQueue = (MSGQUEUE *)hMsgQueueHandle;
int iRet = 0;
if(!pMsgQueue || !pvMessage || pMsgQueue->socket_id < 0)
{
return -1;
}
// pthread_rwlock_rdlock(&pMsgQueue->msg_rwlock);
iRet = s_socket_recv(pMsgQueue->socket_id, (unsigned char *)pvMessage, msg_size, uiTimeOutMs);
// pthread_rwlock_unlock(&pMsgQueue->msg_rwlock);
if(iRet < msg_size)
{
return -1;
}
return 0;
}
#endif
int msg_queue_recv(int iMsgId, void *pMsg, int iMsgSize)
{
#ifdef USE_SOCKET
return s_msg_queue_receive(iMsgId, pMsg, iMsgSize, 0xffffffff);
#else
int iRet = 0;
msg_queue_st msg;
if(iMsgSize <= 0)
{
fprintf(stdout, "message length is less than 0\n");
return -2;
}
memset(&msg, 0, sizeof(msg_queue_st));
msg.msg_type = iMsgId;
iRet = msgrcv(iMsgId, &msg, iMsgSize, 0, 0);
if(iRet < 0 || iRet > iMsgSize)
{
fprintf(stdout, "send msg error:errno=%d, err_msg=%s\n", errno, strerror(errno));
return -1;
}
memcpy(pMsg, msg.msg, iMsgSize);
return 0;
#endif
}
int msg_queue_recv_non_blocking(int iMsgId, void *pMsg, int iMsgSize)
{
#ifdef USE_SOCKET
return s_msg_queue_receive(iMsgId, pMsg, iMsgSize, 0);
#else
int iRet = 0;
msg_queue_st msg;
if(iMsgSize <= 0)
{
fprintf(stdout, "message length is less than 0\n");
return -2;
}
memset(&msg, 0, sizeof(msg_queue_st));
msg.msg_type = iMsgId;
iRet = msgrcv(iMsgId, &msg, iMsgSize, 0, IPC_NOWAIT);
if(iRet < 0 || iRet > iMsgSize)
{
if(errno != 42)//no msg
fprintf(stdout, "send msg error:errno=%d, err_msg=%s\n", errno, strerror(errno));
return -1;
}
memcpy(pMsg, msg.msg, iMsgSize);
return 0;
#endif
}
int msg_queue_delete(int iMsgId)
{
#ifdef USE_SOCKET
MSGQUEUE *pMsgQueue = (MSGQUEUE *)iMsgId;
if(!pMsgQueue)
{
return 0;
}
if(pMsgQueue->socket_id >= 0)
{
close(pMsgQueue->socket_id);
}
pthread_mutex_destroy(&pMsgQueue->msg_rwlock);
free(pMsgQueue);
return 0;
#else
if(iMsgId < 0)
{
printf("===>[%s, %d]error msg id %d\n", __FUNCTION__, __LINE__, iMsgId);
return -1;
}
if(msgctl(iMsgId, IPC_RMID, 0) == -1)
{
fprintf(stdout, "delete msg error:errno=%d, err_msg=%s\n", errno, strerror(errno));
return -1;
}
return 0;
#endif
}
/********************* local structure **************************************/
typedef struct _msg_st_
{
long int msg_type;
char acMsg[1024];
}MSG_ST;
/**
* @brief message queue test
* @return main function return status.
*/
int main(void)
{
int iMsgId = 0;
MSG_ST stMsg;
if(msg_queue_create(&iMsgId) == -1)
{
return -1;
}
printf("===>[%s, %d]iMsgId=%d\n", __FUNCTION__, __LINE__, iMsgId);
do
{
memset(&stMsg, 0, sizeof(MSG_ST));
snprintf(stMsg.acMsg, sizeof(stMsg.acMsg), "Hello");
stMsg.msg_type = 1;
if(msg_queue_send(iMsgId, &stMsg, sizeof(MSG_ST)) == -1)
{
break;
}
memset(&stMsg, 0, sizeof(MSG_ST));
snprintf(stMsg.acMsg, sizeof(stMsg.acMsg), "asdfasdf234");
stMsg.msg_type = 2;
if(msg_queue_send(iMsgId, &stMsg, sizeof(MSG_ST)) == -1)
{
break;
}
memset(&stMsg, 0, sizeof(MSG_ST));
if(msg_queue_recv(iMsgId, &stMsg, sizeof(MSG_ST)) == -1)
{
break;
}
printf("===>[%s, %d]%ld %s\n", __FUNCTION__, __LINE__, stMsg.msg_type, stMsg.acMsg);
memset(&stMsg, 0, sizeof(MSG_ST));
if(msg_queue_recv(iMsgId, &stMsg, sizeof(MSG_ST)) == -1)
{
break;
}
printf("===>[%s, %d]%ld %s\n", __FUNCTION__, __LINE__, stMsg.msg_type, stMsg.acMsg);
}while(0);
msg_queue_delete(iMsgId);
return 0;
}
练习使用消息队列
最新推荐文章于 2022-12-18 17:30:15 发布