linux操作系统编程——fifo复杂C/S模型

来源:互联网 发布:linux tomcat启动命令 编辑:程序博客网 时间:2024/06/10 08:35

程序要求:

                                                    

程序如下:

 1、server.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>typedef struct      //定义一个数据结构用于fifo中数据传送{    int pid;          //进程号    char message[100];   }package;static void child_read(char * , int *);static void father_write(int *);int main(int argc, char *argv[]){    int server_fifo, client_fifo;    pid_t pid;    int pipe_fd[2];    int open_flag = 0;    if (argc < 2)    {        fprintf(stderr, "usages: %s server_fifo\n", argv[0]);        exit(-1);    }    if (pipe(pipe_fd) < 0)                         //创建pipe用于子进程与父进程之间的通信    {        perror("failed to create pipe");        exit(-1);    }    if ((pid = fork()) < 0)    {        perror("failed to fork pid");        exit(-1);    }    if (pid == 0)        child_read(argv[1], pipe_fd);      //子进程读取fifo中的数据    else         father_write(pipe_fd);             //父进程写入fifo数据      return 0;}static void child_read(char *arg, int *pipe_fd){    package recv_package;    int server_fifo;    char file[20];    int open_flag = 0;      //fifo打开标志    close(pipe_fd[0]);    if (mkfifo(arg, 0666) < 0)      //创建fifo,若已经存在则打开fifo    {        if (errno == EEXIST)        {            if ((server_fifo = open(arg, O_RDWR)) < 0)            {                perror("failed to open server_fifo");                exit(-1);            }            open_flag = 1;        }    }    if (open_flag == 0)    {        if ((server_fifo = open(arg, O_RDWR)) < 0)        {            perror("failed to open server_fifo");            exit(-1);        }    }    while (read(server_fifo, &recv_package, sizeof(recv_package)) > 0)         //读取fifo中的数据        {        sprintf(file, "%d\0", recv_package.pid);  //将客户端的进程号作为客户的专用fifo名            printf("recv: %s\n", recv_package.message);        write(pipe_fd[1], file, strlen(file) + 1);  //将客户端专用fifo名传送给父进程    }        return ;}static void father_write(int *pipe_fd){    char buf[100];    char file[20];    int client_fifo;    close(pipe_fd[1]);    while(read(pipe_fd[0], file, sizeof(file)) > 0)    //读取pipe数据,获取客户端专用fifo文件名    {        if ((client_fifo = open(file, O_WRONLY)) < 0)    //打开客户专用fifo        {            perror("failed to open client_fifo");            exit(-1);        }        printf("server>");        fgets(buf, sizeof(buf), stdin);        buf[strlen(buf) - 1] = 0;        write(client_fifo, buf, strlen(buf) + 1);    //往客户专用fifo中写入数据    }    return ;}
2、client.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>typedef struct{    int pid;    char message[100];}package;static void child_read(void);static void father_write(int , int );int main(int argc, const char *argv[]){    int server_fifo;    pid_t pid;    int pipe_fd[2];    if (argc < 2)    {        fprintf(stderr, "usages: %s server_fifo\n", argv[0]);        exit(-1);    }    if ((server_fifo = open(argv[1], O_RDWR)) < 0)    //打开众所周知的fifo    {        perror("failed to open server_fifo");        exit(-1);    }    if ((pid = fork()) < 0)    {        perror("failed to fork pid");        exit(-1);    }    if (pid == 0)        child_read();      //子进程读    else        father_write(server_fifo, pid);       //父进程写    return 0;}static void child_read(void){    char buf[100];    char file[20];    int client_fifo;    int open_flag = 0;    sprintf(file, "%d\0", getpid());    if (mkfifo(file, 0666) < 0)     //用自己的进程号为fifo文件名,创建fifo    {        if (errno == EEXIST)        {            if ((client_fifo = open(file, O_RDONLY)) < 0)            {                perror("failed to open client_fifo");                exit(-1);            }            open_flag = 1;        }    }    if (open_flag == 0)    {        if ((client_fifo = open(file, O_RDONLY)) < 0)        {            perror("failed to open client_fifo");            exit(-1);        }    }    while (read(client_fifo, buf, sizeof(buf)) > 0)   //读取客户专用fifo中的数据        printf("recv: %s\n", buf);    return ;}static void father_write(int server_fifo, int pid){    package send_package;    char buf[100];    while (1)    {        printf(">");        fgets(buf, sizeof(buf), stdin);        buf[strlen(buf) - 1] = 0;        //往数据结构中填充数据        strcpy(send_package.message, buf);                send_package.pid = pid;                    write(server_fifo, &send_package, sizeof(send_package));      //往众所周知的fifo中写入数据    }    return ;}

注:该程序还存在一定的问题等待改善,但是可以基本实现以上模型的功能

   1、服务器端在应对多客户端情况下,存在一定的混乱问题

   2、服务器端收到客户端请求后只能写回答一次,要再次写回答需要客户端再次发送请求,否则会出现错误!