c - 使用 2 个 FIFO 的客户端-服务器 ipc 消息中的 kill() 函数问题

标签 c unix client-server ipc fifo

我想通过 2 个单向 FIFO 发送和接收消息

数据流

FIFO1 
stdin--->parent(client) writefd--->FIFO1-->child(server) readfd
FIFO2
child(server) writefd2---->FIFO2--->parent(client) readfd2--->stdout

I need to have boundary structed message mesg_len+mesg_type+mesg_data

The function is that if user input "Knock Knock" on stdin, which directs to client, client send this message to server through FIFO1, server compares the string, if matches with "Knock Knock", then server reply message "Who's there?" to client through FIFO2, and client write this message to the stdout.

The interactive part is like:

client:Knock Knock
server:who's there
client:eric
server:eric,welcome
client:exit
all signal terminate

Below is my code:

I need help on kill() signals when client types "exit".It seems the client process still live after call kill(). So i need to type ctrl+c to end

Please help me. Thanks a lot!

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

#define MAX_BUF 100
#define MAXMESGDATA (MAX_BUF - 2* sizeof(long))
#define MESGHDRSIZE (sizeof(struct mymesg)-MAXMESGDATA)
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

struct mymesg{
    long mesg_len; //byte in mesg_data
    long mesg_type; //message type
    char mesg_data[MAXMESGDATA];
};

ssize_t mesg_send (int fd, struct mymesg *mptr){
    return (write (fd,mptr,MESGHDRSIZE + mptr->mesg_len));
}

ssize_t mesg_recv(int fd,struct mymesg *mptr){
    size_t len;
    ssize_t n;
    if ((n=read(fd,mptr,MESGHDRSIZE))==0) {//read hear first, get len of data
        return 0; //end of file
    } else if (n!=MESGHDRSIZE){
        printf("message header: expected %d, got %d\n", MESGHDRSIZE,n);
        exit(1);
    }
    if ((len=mptr->mesg_len)>0)
    {
        if ((n=read(fd,mptr->mesg_data,len))!=len)
        {
            printf("message data: expected %d, got %d\n", len,n);
            exit(1);
        }
    }
    return len;
}

void client(int readfd,int writefd){
    size_t len;
    ssize_t n;
    struct mymesg mesg;
    for (;;)
    {
        printf("\nClient:");
        fgets(mesg.mesg_data,MAXMESGDATA,stdin);//read mesg
        len=strlen(mesg.mesg_data);

        if (mesg.mesg_data[len-1]=='\n') //ignore newline
            len--;
        mesg.mesg_len=len;
        mesg.mesg_type=1;

        mesg_send(writefd,&mesg);//write to IPC channel
        //read from IPC,write to std output
        if((n=mesg_recv(readfd,&mesg))>0)
            write(STDOUT_FILENO,mesg.mesg_data,n);
    }
}

void server(int readfd,int writefd){
    ssize_t n;
    struct mymesg mesg;
    for(;;)
    {
        mesg.mesg_type=1;
        //read from IPC channel
        if ((n=mesg_recv(readfd,&mesg))==0){
            printf("Message missing");
            exit(1);
        }

        mesg.mesg_data[n]='\0';
        mesg.mesg_len=strlen(mesg.mesg_data);
        char* str=NULL;

        if (strcasecmp ("Knock Knock", mesg.mesg_data)==0){
             str="Server:Who's there?";
             strcpy(mesg.mesg_data,str);
             mesg.mesg_len=strlen(str)-1;
            }
        else if(strcasecmp ("Eric", mesg.mesg_data)==0){
            str="Server:Eric,Welcome!";
            strcpy(mesg.mesg_data,str);
            mesg.mesg_len=strlen(str)-1;
            }
        else if(strcasecmp ("Exit", mesg.mesg_data)==0){
            kill(getpid(),SIGTERM);
            kill(getppid(),SIGTERM);
            exit(0);
            }
        mesg_send(writefd,&mesg);
    }
}

int main(int argc, char ** argv){
    /*MAXMESGDATA== 92 bytes; sizeof(struct mymesg)== 100 bytes
     2* sizeof(long)== 8 bytes; MESGHDRSIZE ==8 bytes*/

    int readfd,writefd;
    pid_t childpid;
    //create 2 FIFOs
    if ((mkfifo(FIFO1,FILE_MODE)<0) && (errno!=EEXIST)){
        printf("can't create %s",FIFO1);
        exit(1);
    }
    if ((mkfifo(FIFO2,FILE_MODE)<0) && (errno!=EEXIST)){
        printf("can't create %s",FIFO1);
        unlink(FIFO1);
        exit(1);
    }
    if ((childpid=fork()==0)){//child
        readfd=open(FIFO1,O_RDONLY,0);
        writefd=open(FIFO2,O_WRONLY,0);
        server(readfd,writefd);
        exit(0);
    }
    //parent
    writefd=open(FIFO1,O_WRONLY,0);
    readfd=open(FIFO2,O_RDONLY,0);
    client(readfd,writefd);

    waitpid(childpid,NULL,0);
    close(readfd);
    close(writefd);
    unlink(FIFO1);
    unlink(FIFO2);
    return EXIT_SUCCESS;
}

最佳答案

在这两个进程中,您以 WRONLY 方式打开 FIFO2,以 RDONLY 方式打开 FIFO1。打开管道进行读取将阻塞,直到另一侧打开进行写入,并且您在两侧都打开进行读取 - 因此陷入僵局。

关于c - 使用 2 个 FIFO 的客户端-服务器 ipc 消息中的 kill() 函数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6290530/

相关文章:

c - 使用 Turbo C 在 C 语言中进行 GUI 编程

bash - 传送到命令 : is there any standard? 后尾随新行

C# 客户端 - 服务器套接字断开处理

c - 如何打开和打印目录中的所有文件

android - 如何通过服务器连接2个Android手机

java - Jersey REST 请求对象更改

c - 如何格式化在 C 中指定一个 const char *?

c++ - 不释放内存是否可以接受

c - pthreads的生产者消费者问题

linux - 如何在多台机器上执行 ps 来监控它们的性能