Проблема функции kill () в сообщении ipc клиент-сервер с использованием 2 FIFO - PullRequest
1 голос
/ 09 июня 2011

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

Поток данных

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

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

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

Интерактивная часть выглядит так:

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

Ниже мой код:

Мне нужна помощь поkill () сигнализирует, когда клиент набирает «exit». Кажется, что клиентский процесс все еще жив после вызова 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;
}

1 Ответ

0 голосов
/ 10 июня 2011

Вы открываете FIFO2 как НЕПРАВИЛЬНО и FIFO1 как ПОЛУЧЕНО в обоих процессах. Открытие канала для чтения будет блокироваться до тех пор, пока другая сторона не откроется для записи, и вы не откроете для чтения с обеих сторон - следовательно, будете заблокированы.

...