проблема с функцией kill () в ipc-сообщении клиент-сервер с использованием 2 FIFOs

#c #unix #client-server #ipc #fifo

#c #unix #клиент-сервер #ipc #фифо #fifo

Вопрос:

Я хочу, чтобы сообщение отправлялось и получалось через 2 однонаправленных FIFO

Поток данных

FIFO1 
stdin---> родительский (клиентский) writefd---> FIFO1-> дочерний (серверный) readfd
FIFO2
дочерний (серверный) writefd2----> FIFO2---> родительский (клиентский) readfd2---> стандартный вывод

Мне нужно иметь сообщение с граничной структурой mesg_len mesg_type mesg_data

Функция заключается в том, что если пользователь вводит «Knock Knock» в stdin, который направляет к клиенту, клиент отправляет это сообщение на сервер через FIFO1, сервер сравнивает строку, если совпадает с «Knock Knock», затем сервер отвечает сообщением «Кто там?» клиенту через FIFO2, и клиент записывает это сообщение в стандартный вывод.

Интерактивная часть похожа:

клиент: Тук-тук 
сервер: кто там 
клиент: Эрик 
сервер: Эрик, добро пожаловать 
клиент: выход 
завершение всех сигналов

Ниже приведен мой код:

Мне нужна помощь по сигналам 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 %dn", 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 %dn", 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,amp;mesg);//write to IPC channel
        //read from IPC,write to std output
        if((n=mesg_recv(readfd,amp;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,amp;mesg))==0){
            printf("Message missing");
            exit(1);
        }

        mesg.mesg_data[n]='';
        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,amp;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) amp;amp; (errno!=EEXIST)){
        printf("can't create %s",FIFO1);
        exit(1);
    }
    if ((mkfifo(FIFO2,FILE_MODE)<0) amp;amp; (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;
}
  

Комментарии:

1. Если это домашнее задание, вы должны пометить его как таковое. Что еще более важно, многие программисты на языке C обычно не сканируют вопросы, помеченные только как unix, поэтому соответствующий языковой тег поможет # людям, которые рассматривают вашу проблему. Удачи.

Ответ №1:

Вы открываете FIFO2 как WRONLY, а FIFO1 как RDONLY в обоих процессах. Открытие канала для чтения будет блокироваться до тех пор, пока другая сторона не откроется для записи, и вы не откроетесь для чтения с обеих сторон — следовательно, зашли в тупик.

Комментарии:

1. @Juanita — вместо использования kill , что очень жестоко, используйте свою систему обмена сообщениями, чтобы отправить клиенту сообщение о выходе.

2. Домашнее требование состоит в том, чтобы прекратить все сигналы, выйти из программы, когда клиент вводит «exit». пожалуйста, помогите.