第二十七章 system v消息队列(三)

消息队列实现回射客户/服务器

第二十七章 system v消息队列(三)_第1张图片

msg_srv.c

#include 
#include 
#include 
#include 
#include 
#include 

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

#define MSGMAX 8192
struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[MSGMAX];    /* message data */
};

void echo_srv(int msgid)
{   
    int nRec = 0;
    struct msgbuf msg;

    while(1)
    {
        if( (nRec = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0)
            ERR_EXIT("msgsnd");
        
        int pid;
        pid = *((int*)msg.mtext);
        fputs(msg.mtext+4,stdout);
        msg.mtype = pid;
        msgsnd(msgid, &msg, nRec, 0);
    }
}

int main(int argc, char* argv[])
{
    int msgid;
    msgid = msgget(1234,IPC_CREAT|0666);
    if(msgid == -1)
        ERR_EXIT("msgget");

    printf("msget success, msgid=%d\n",msgid); 

    echo_srv(msgid);

    return 0;
}

msg_cli.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

#define MSGMAX 8192
struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[MSGMAX];    /* message data */
};

void echo_cli(int msgid)
{
    int pid,nRec;
    struct msgbuf msg;
    memset(&msg, 9, sizeof(msg));
    pid = getpid();
    *((int*)msg.mtext) = pid;

    while(fgets(msg.mtext+4, MSGMAX, stdin) != NULL)
    {
        msg.mtype = 1;
        
        if(msgsnd(msgid, &msg, 4+strlen(msg.mtext+4), 0) < 0)
            ERR_EXIT("msgsnd");
        
        memset(msg.mtext+4, 0, MSGMAX-4);
        if( (nRec = msgrcv(msgid, &msg, MSGMAX, pid, 0)) < 0)
            ERR_EXIT("msgsnd");

        fputs(msg.mtext+4, stdout);
        memset(msg.mtext+4, 0, MSGMAX-4);
    }

}

int main(int argc, char const *argv[])
{
    int msgid;
    msgid = msgget(1234,0);
    if(msgid == -1)
        ERR_EXIT("msgget");

    echo_cli(msgid);

    return 0;
}

  当服务器端收到客户端的请求之后,需要向客户端回射数据, 此时服务器端处于往消息队列发送消息的状态;
这时很多客户端发起很多的请求,将队列读满了,此时服务器端发送将阻塞;而客户端也阻塞等待读取数据,这时就产生了死锁
如果使用非阻塞的模式发送,因为队列满了,没有办法往消息队列中填充数据,会返回EAGAIN错误,又迫使服务器再次往消息队列中填充数据,此时客户端依旧无法获取到数据
第二十七章 system v消息队列(三)_第2张图片

msg_cli.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

#define MSGMAX 8192
struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[MSGMAX];    /* message data */
};

void echo_cli(int snd_msgid, int rcv_msgid)
{
    int pid,nRec;
    struct msgbuf msg;
    memset(&msg, 9, sizeof(msg));
    *((int*)msg.mtext) = rcv_msgid;

    while(fgets(msg.mtext+4, MSGMAX, stdin) != NULL)
    {
        msg.mtype = 1;
        
        if(msgsnd(snd_msgid, &msg, 4+strlen(msg.mtext+4), 0) < 0)
            ERR_EXIT("msgsnd");
        
        sleep(1);
        memset(msg.mtext+4, 0, MSGMAX-4);
        if( (nRec = msgrcv(rcv_msgid, &msg, MSGMAX, 2, 0)) < 0)
            ERR_EXIT("msgrcv");

        fputs(msg.mtext+4, stdout);
        memset(msg.mtext+4, 0, MSGMAX-4);
    }

}


int main(int argc, char const *argv[])
{

    int snd_msgid, rcv_msgid;
    snd_msgid = msgget(1234,0);
    rcv_msgid = msgget(IPC_PRIVATE,0666);
    if(snd_msgid == -1 || rcv_msgid == -1)
        ERR_EXIT("msgget");

    echo_cli(snd_msgid,rcv_msgid);

    return 0;
}

msg_srv.c

#include 
#include 
#include 
#include 
#include 
#include 

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

#define MSGMAX 8192
struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[MSGMAX];    /* message data */
};

void echo_srv(int msgid)
{   
    int nRec = 0;
    pid_t pid;
    struct msgbuf msg;

    while(1)
    {
        if( (nRec = msgrcv(msgid, &msg, MSGMAX, 1, 0)) < 0)
            ERR_EXIT("msgsnd");
        
        fputs(msg.mtext+4,stdout);

        pid = fork();
        if(pid == 0)
        {
            int nSnd;
            int rcv_msgid;
            rcv_msgid = *((int*)msg.mtext);
        
            msg.mtype = 2;
            nSnd = msgsnd(rcv_msgid, &msg, nRec, 0);
            if(nSnd == -1)
            {
                perror("msgsnd");
            }            
        }
    }
}

int main(int argc, char* argv[])
{
    int msgid;
    msgid = msgget(1234,IPC_CREAT|0666);
    if(msgid == -1)
        ERR_EXIT("msgget");

    echo_srv(msgid);

    return 0;
}

你可能感兴趣的:(第二十七章 system v消息队列(三))