System V消息队列(三):简单并发服务器

本文介绍了如何运用Makefile构建一个基于System V消息队列的简单并发服务器。文中涉及到的文件结构包括主文件夹下的Makefile、头文件、依赖库文件以及客户端和服务端的源代码。虽然Makefile编写可能不够完美,但足以应对基本需求。如遇到问题,欢迎留言讨论。
摘要由CSDN通过智能技术生成

简单并发服务器

联系Makefile的方式就是使用它,所以在这段代码中简单的使用了Makefile,现学现卖。可能有点瑕疵,但是简单使用应该没有大问题。如有问题,还请留言留言。

主文件夹下./Makefile

CC=gcc
FLAGS= -Wall -g -lrt

TOPDIR := $(PWD)
SUBDIR := server client
OBJLINK = --std=c99
HEADDIR := $(TOPDIR)/include

DEPENDS := $(wildcard $(TOPDIR)/lib/*.c)

export CC FLAGS HEARD OBJLINK HEADDIR DEPENDS

all: $(SUBDIR) OBJ

OBJ:
        make -C $(TOPDIR)/lib

LIB := $(wildcard $(TOPDIR)/lib/*.o)
#CHECKDIR:
#       mkdir -p $(SUBDIR) $(BUBDIR)

$(SUBDIR):RUN
        make -C $@

RUN:

.PHONY:clean

clean:
        rm -rf $(OBJDIR)/*.o

头文件./include/

myhead.h

#ifndef MYHEAD_H_
#define MYHEAD_H_

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<mqueue.h>
#include<sys/msg.h>

#define MSG_R 0400
#define MSG_W 0200
#define SVMSG (MSG_R | MSG_W | MSG_R >> 3 | MSG_W >> 3)
#define MAXLINE         4096
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)

struct msgbuf
{
    __syscall_slong_t mtype;    /* type of received/sent message */
    char mtext[1];              /* text of the message */
};

#define MQ_KEY1 1234L
#define MQ_KEY2 2345L

#endif

mesg.h

#ifndef MESG_H_
#define MESG_H_

#include"myhead.h"

#define MAXMESGDATA (MAXLINE-2*sizeof(long))
#define MQ_KEY1 1234L

#define MESHDRSIZE (sizeof(struct mymsg) - MAXMESGDATA)

struct mymsg
{
        long len;
        long type;
        char data[MAXLINE];
};

ssize_t mesg_send(int, struct mymsg*);
//void Mesg_send(int, struct mymsg*);
ssize_t mesg_recv(int, struct mymsg*);
//ssize_t Mesg_recv(int, struct mymsg*);
void sig_chld(int signo);

#endif

简单依赖文件./lib/

Makefile

SOURCES := $(wildcard *.c)
TARGETS := $(patsubst %.c, %.o, $(SOURCES))

all:$(TARGETS)

$(TARGETS):%.o:%.c
        $(CC) -c $< $(FLAGS) -o $@  -I$(HEADDIR)

clean:
        -rm -rf *.o

recv.c

#include"mesg.h"

ssize_t mesg_recv(int fd, struct mymsg *msg)
{
        ssize_t n = 0;

        do
        {
                n = msgrcv(fd, &(msg->type), MAXMESGDATA, msg->type, 0);
        }while(n == -1 && errno == EINTR);

        if(n < 0)
                perror("recv error");
        msg->len = n;
        return n;
}

send.c

#include"mesg.h"

ssize_t mesg_send(int fd, struct mymsg* msg)
{
        return (msgsnd(fd, &(msg->type), msg->len, 0));
}

wait.c

#include"mesg.h"

void sig_chld(int signo)
{
        pid_t pid;
        int stat;

        while((pid = waitpid(-1, &stat, WNOHANG)) > 0);
        return;
}

client文件 ./client/

SOURCES := $(wildcard *.c)
#TARGETS := $(patsubst %.c, %, $(SOURCES))

#all:$(TARGETS)

#$(TARGETS):%.o:%.c
client:$(SOURCES)
        $(CC) $^ $(DEPENDS) $(FLAGS) -o $@ -I$(HEADDIR)

.PHONY:clean

clean:
        -rm -rf *.o

client_main.c

#include"mesg.h"

void client(int, int);

int main(int argc, char **argv)
{
        int readid, writeid;

        writeid = msgget(MQ_KEY1, 0);
        readid = msgget(IPC_PRIVATE, SVMSG | IPC_CREAT);

        client(readid, writeid);

        msgctl(readid, IPC_RMID, NULL);
        return 0;
}

client.c

#include"mesg.h"

void client(int readfd, int writefd)
{
        ssize_t len;
        struct mymsg msg;
        char * ptr = NULL;

        snprintf(msg.data, MAXMESGDATA, "%d", readfd);
        len = strlen(msg.data);

        ptr = msg.data + len + 1;
        msg.data[len] = ' ';

        fgets(ptr, MAXMESGDATA - len - 1, stdin);
        len = strlen(msg.data);

        if(msg.data[len - 1])
        {
                len--;
        }
        msg.len = len;
        msg.type = 1;

        len = mesg_send(writefd, &msg);

        sleep(1);

        while((len = mesg_recv(readfd, &msg)) > 0)
        {
                write(STDOUT_FILENO, msg.data, len);
        }
        sleep(10);
        return;
}

server文件./server/

Makefile

SOURCES := $(wildcard *.c)
#TARGETS := $(patsubst %.c, %.o, $(SOURCES))

#all:$(TARGETS)

#$(TARGETS):%.o:%.c
server:$(SOURCES)
        $(CC) $^ $(DEPENDS) $(FLAGS) -o $@ -I$(HEADDIR)

.PHONY:clean

clean:
        -rm -rf *.o

server_main.c

#include"mesg.h"

void server(int, int);

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

        msqid = msgget(MQ_KEY1, SVMSG | IPC_CREAT);
        server(msqid, msqid);

        return 0;
}

server.c

#include"mesg.h"

void server(int readfd, int writefd)
{
        ssize_t len;
        struct mymsg msg;
        FILE* fp = NULL;
        char * ptr = NULL;

        msg.type = 0;
        signal(SIGCHLD, sig_chld);

        for(;;)
        {
                msg.type = 1;
                len = mesg_recv(readfd, &msg);
                msg.data[len] = '\0';
                printf("recv %s\n", msg.data);

                if(NULL == (ptr = strchr(msg.data, ' ')))
                {
                        printf("error geshi\n");
                        continue;
                }
                ptr++;

                writefd = atoi(msg.data);
                if(fork() == 0)
                {
                        if((fp = fopen(ptr, "r")) == NULL)
                        {
                                snprintf(msg.data + len, sizeof(msg.data) - len, ": can not open, %s\n", strerror(errno));
                                msg.len = strlen(ptr);
                                memmove(msg.data, ptr, msg.len);
                                mesg_send(writefd, &msg);
                                continue;
                        }

                        while(NULL!= fgets(msg.data, MAXMESGDATA, fp))
                        {
                                msg.len = strlen(msg.data);
                                mesg_send(writefd, &msg);
                        }
                        fclose(fp);
                        msg.len = 0;
                        mesg_send(writefd, &msg);
                        exit(0);
                }
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值