System V消息队列实现服务器

每个应用一个队列

/*服务器程序*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/msg.h>
#include<fcntl.h>
#include<limits.h>
#include<errno.h>
#include<string.h>
//#define SVMSG_MODE ()
#define MQ_KEY1 1231L
#define MQ_KEY2 2340L
#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))
//#define MESGHDRSIZE (sizeof(st))
struct mymesg
{
    long mesg_len;
    long mesg_type;
    char mesg_data[MAXMESGDATA];
};
#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)

void server(int, int);
ssize_t mesg_send(int, struct mymesg*);
ssize_t mesg_recv(int, struct mymesg*);

int main(int argc, char **argv)
{
    int msqid;

    /*创建消息队列*/
    msqid = msgget(MQ_KEY1, 0666 | IPC_CREAT);
    server(msqid, msqid);/*读写都是一个队列*/
    exit(0);
}
/*发送消息*/
ssize_t mesg_send(int id, struct mymesg *mptr)
{
    return msgsnd(id, &(mptr->mesg_type), mptr->mesg_len, 0);
}
/*接受消息*/
ssize_t mesg_recv(int id, struct mymesg *mptr)
{
    ssize_t n;

    n = msgrcv(id, &(mptr->mesg_type), MAXMESGDATA, mptr->mesg_type, 0);
    return n;
}
void server(int readfd, int writefd)
{
    struct mymesg mesg;
    size_t len;
    ssize_t n;
    char *ptr;
    unsigned long pid;
    FILE *fp;

    while(1)/*服务器一直在运行*/
    {
        mesg.mesg_type = 1;/*表示从客户端到服务器的数据*/
        if((n = mesg_recv(readfd, &mesg)) == 0)/*读取路径名和pid*/
            continue;
        printf("%s\n", mesg.mesg_data);
        if((ptr = strchr(mesg.mesg_data, ' ')) == NULL)
            continue;
        mesg.mesg_data[n] = '\0';
        *ptr++ = 0;/*ptr现在指向路径名*/
        //len = strlen(ptr);
        //ptr[len] = '\0';
        pid = atol(mesg.mesg_data);/*该函数以空格结束*/

        mesg.mesg_type = pid;/*表示从服务器发送到客户端的数据*/
        if((fp = fopen(ptr, "r")) == NULL)
        {
            printf("fopen failed\n");
            /*error: must tell client*/
        //  mesg.mesg_type = pid;
            snprintf(mesg.mesg_data+n, sizeof(mesg.mesg_data)-n, ":can't open %s\n", strerror(errno));
            mesg.mesg_len = strlen(mesg.mesg_data);
            mesg_send(writefd, &mesg);

        }
        else
        {
            while(fgets(mesg.mesg_data, MAXMESGDATA, fp) != NULL)/*从文件中读取数据*/
            {
                 mesg.mesg_len = strlen(mesg.mesg_data);
                 mesg_send(writefd, &mesg);
            }
            fclose(fp);
        }
    }
    /*send a 0-length message to signify the end*/
    mesg.mesg_len = 0;
    mesg_send(writefd, &mesg);
}
/*客户端程序*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/msg.h>
#include<fcntl.h>
#include<limits.h>
#include<errno.h>
#include<string.h>
//#define SVMSG_MODE ()
#define MQ_KEY1 1231L
#define MQ_KEY2 2340L
#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))
//#define MESGHDRSIZE (sizeof(st))
struct mymesg
{
    long mesg_len;
    long mesg_type;
    char mesg_data[MAXMESGDATA];
};
#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)

void client(int, int);
ssize_t mesg_send(int, struct mymesg*);
ssize_t mesg_recv(int, struct mymesg*);

int main(int argc, char **argv)
{
    int msqid;

    /*打开消息队列*/
    msqid = msgget(MQ_KEY1, 0);
    client(msqid, msqid);/*读写都是一个队列*/
    exit(0);
}
/*发送消息*/
ssize_t mesg_send(int id, struct mymesg *mptr)
{
    return msgsnd(id, &(mptr->mesg_type), mptr->mesg_len, 0);
}
/*接受消息*/
ssize_t mesg_recv(int id, struct mymesg *mptr)
{
    ssize_t n;

    n = msgrcv(id, &(mptr->mesg_type), MAXMESGDATA, mptr->mesg_type, 0);
    return n;
}
void client(int readfd, int writefd)
{
    struct mymesg mesg;
    pid_t pid;
    size_t len;
    ssize_t n;

    pid = getpid();
    snprintf(mesg.mesg_data, MAXMESGDATA, "%ld ", (long)pid);
    len = strlen(mesg.mesg_data);
    /*读取路径*/
    fgets(mesg.mesg_data+len, sizeof(mesg.mesg_data)-len, stdin);
    printf("%s\n", mesg.mesg_data);
    len = strlen(mesg.mesg_data);
    if(mesg.mesg_data[len-1] == '\n')
        len--;
    mesg.mesg_len = len;
    mesg.mesg_type = 1;/*表示从客户端发往服务器的数据*/
    /*向服务器发送请求*/
    mesg_send(writefd, &mesg);

    mesg.mesg_type = (long)pid;
    while((n = mesg_recv(readfd, &mesg)) >0)
        write(STDOUT_FILENO, mesg.mesg_data, n);
}

每个客户一个队列

/*************************************************************************
    > File Name: client.c
    > Author: ndj
    > Mail: ndj_ydd@163.com 
    > Created Time: Fri 10 Nov 2017 09:54:16 AM CST
 ************************************************************************/
/*服务器程序*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/msg.h>
#include<string.h>
#include<errno.h>
#include<limits.h>
#include<signal.h>
#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))
#define SERVER_KEY 1234L/*服务器消息队列,众所周知的键*/
struct mymesg
{
    long mesg_len;
    long mesg_type;
    char mesg_data[MAXMESGDATA];
};
#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)

ssize_t mesg_send(int, struct mymesg*);/*发送消息*/
ssize_t mesg_rcv(int, struct mymesg*); /*接受消息*/
void client(int, int);
void sig_chld(int);

int main(int argc, char **argv)
{
    int readid, writeid;/*消息队列描述符*/
    struct mymesg mesg;
    size_t len;
    ssize_t n;
    pid_t pid;
    char *ptr;
    FILE *fp;

    signal(SIGCHLD, sig_chld);/*注册信号处理函数*/
    /*创建众所周知的消息队列*/
    readid = msgget(SERVER_KEY, IPC_CREAT | IPC_EXCL | 0666);

    while(1)
    {
        if((n = mesg_rcv(readid, &mesg)) == 0)/*父进程在这里接受消息*/
            continue;

        if((pid = fork()) < 0)
        {
            fprintf(stderr, "fork failed\n");
            exit(EXIT_FAILURE);
        }
        else if(pid == 0)/*子进程,处理消息*/
        {
            mesg.mesg_data[n] = '\0';
            if((ptr = strchr(mesg.mesg_data, ' ')) == NULL) 
                exit(EXIT_FAILURE);/*退出子进程*/
            *ptr++ = 0;/*ptr指向pathname*/
            writeid = atol(mesg.mesg_data);/*客户端创建的消息队列,描述符*/
            mesg.mesg_type = 1;/*给type赋值*/

            /*打开文件*/
            if((fp = fopen(ptr, "r")) == NULL)
            {
                /*error: must tell client*/
                snprintf(mesg.mesg_data+n, MAXMESGDATA-n, ":can't open %s\n", strerror(errno));
                mesg.mesg_len = strlen(mesg.mesg_data);
                mesg_send(writeid, &mesg);
            }
            /*从文件中读取数据*/
            else
            {
                while(fgets(mesg.mesg_data, MAXMESGDATA, fp) != NULL)
                {
                    mesg.mesg_len = strlen(mesg.mesg_data);
                    mesg_send(writeid, &mesg);
                }
                fclose(fp);
            }
            mesg.mesg_len = 0;
            mesg_send(writeid, &mesg);
            exit(EXIT_SUCCESS);/*子进程退出*/
        }

    }
}

ssize_t mesg_send(int fd, struct mymesg *mesg)
{
    return msgsnd(fd, &(mesg->mesg_type), mesg->mesg_len, 0);
}

ssize_t mesg_rcv(int fd, struct mymesg *mesg)
{
    ssize_t n;

    n = msgrcv(fd, &(mesg->mesg_type), MAXMESGDATA,mesg->mesg_type, 0);
    mesg->mesg_len = n;
    return n;
}

/*信号处理函数:避免僵尸进程*/
void sig_chld(int signo)
{
    pid_t pid;
    int stat;
    while((pid = waitpid(-1, &stat,WNOHANG)) > 0);
    return;
}
/*************************************************************************
    > File Name: client.c
    > Author: ndj
    > Mail: ndj_ydd@163.com 
    > Created Time: Fri 10 Nov 2017 09:54:16 AM CST
 ************************************************************************/
/*客户端程序*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/msg.h>
#include<string.h>
#include<errno.h>
#include<limits.h>
#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))
#define SERVER_KEY 1234L/*服务器消息队列,众所周知的键*/
struct mymesg
{
    long mesg_len;
    long mesg_type;
    char mesg_data[MAXMESGDATA];
};
#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)

ssize_t mesg_send(int, struct mymesg*);/*发送消息*/
ssize_t mesg_rcv(int, struct mymesg*); /*接受消息*/
void client(int, int);

int main(int argc, char **argv)
{
    int readid, writeid;/*消息队列描述符*/

    writeid = msgget(SERVER_KEY, 0);/*引用服务器已经存在的消息队列*/
    readid = msgget(IPC_PRIVATE, IPC_CREAT | IPC_EXCL | 0666);/*创建客户端自己的消息队列用于接受消息*/

    client(readid, writeid);
    exit(0);
}

ssize_t mesg_send(int fd, struct mymesg *mesg)
{
    return msgsnd(fd, &(mesg->mesg_type), mesg->mesg_len, 0);
}

ssize_t mesg_rcv(int fd, struct mymesg *mesg)
{
    ssize_t n;

    n = msgrcv(fd, &(mesg->mesg_type), MAXMESGDATA,mesg->mesg_type, 0);
    mesg->mesg_len = n;
    return n;
}

void client(int readfd, int writefd)
{
    struct mymesg mesg;
    ssize_t n;
    size_t len;

    mesg.mesg_type = 1;
    snprintf(mesg.mesg_data, MAXMESGDATA, "%d ", readfd);
    len = strlen(mesg.mesg_data);
    fgets(mesg.mesg_data+len, MAXMESGDATA-n, stdin);
    len = strlen(mesg.mesg_data);
    if(mesg.mesg_data[len-1] == '\n')
        len--;
    mesg.mesg_len = len;
    mesg_send(writefd, &mesg);/*发送 msqid+pathname*/
    mesg.mesg_type = 0;
    while((n = mesg_rcv(readfd, &mesg)) > 0)
        write(STDOUT_FILENO, mesg.mesg_data, n);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值