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

Posted

技术标签:

【中文标题】使用 2 个 FIFO 的客户端-服务器 IPC 消息中的 kill() 函数问题【英文标题】:kill() function problem in client-server ipc message using 2 FIFOs 【发布时间】:2011-06-09 09:11:54 【问题描述】:

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

数据流

先进先出1 stdin--->parent(client) writefd--->FIFO1-->child(server) readfd 先进先出2 子(服务器)writefd2---->FIFO2--->父(客户端)readfd2--->stdout

我需要有边界结构化消息mesg_len+mesg_type+mesg_data

功能是,如果用户在stdin上输入“Knock Knock”,指向客户端,客户端通过FIFO1将此消息发送到服务器,服务器比较字符串,如果匹配到“Knock Knock”,则服务器回复消息“Who's那里?”通过 FIFO2 到客户端,客户端将此消息写入标准输出。

交互部分是这样的:

客户:敲敲 服务器:谁在那里 客户:埃里克 服务器:eric,欢迎 客户:退出 所有信号终止

下面是我的代码:

当客户端键入“exit”时,我需要有关 kill() 信号的帮助。似乎调用 kill() 后客户端进程仍然存在。所以我需要输入 ctrl+c 来结束

请帮助我。非常感谢!

#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;

【问题讨论】:

如果这是家庭作业,你应该这样标记它。更重要的是,许多 C 语言程序员通常不会扫描仅标记为 unix 的问题,因此适当的语言标记将有助于查看您的问题的人数。祝你好运。 【参考方案1】:

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

【讨论】:

@Juanita - 不要使用非常残酷的kill,而是使用您的消息系统向客户端发送消息以退出。 作业要求是终止所​​有信号,当客户端键入“exit”时退出程序。请帮忙。

以上是关于使用 2 个 FIFO 的客户端-服务器 IPC 消息中的 kill() 函数问题的主要内容,如果未能解决你的问题,请参考以下文章

IPC - 命名管道(fifo)- 使用

IPC - 命名管道(fifo)- 使用

IPC - 命名管道(fifo)- 使用

IPC - 命名管道(fifo)- 使用

IPC通信_有名管道(FIFO)

Linux IPC之管道和FIFO