练习使用消息队列

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值