Lois2B
Lois2B

Reputation: 121

How to make server process wait for second read() from FIFO?

My server and client are communicating back and forth using two named pipes (fifo) in C until the server receives an exit message. Apparently the server side blocks the second time it tries to read() from its FIFO despite the client writing to it successfully. I think the problem is that the server tries to read() sooner than the client could write() to it.

Here is the server:

#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "header.h"
#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {

        //fifo for the server to read from
        if (mkfifo(FIFONAME, S_IFIFO|0666) < 0) {
                if (errno != EEXIST) {
                        perror("Error with mkfifo");
                        exit(1);
                }
        }

        int f;
        if ((f = open(FIFONAME, O_RDONLY)) < 0) {
                perror("Error with open");
                exit(1);
        }

        Message msg;

        while(1) {
                if ((read(f, &msg, sizeof(Message))) > 0) {
                        if (strcmp(msg.user, "exit") == 0) {
                                close(f);
                                unlink(FIFONAME);
                                exit(0);
                        }
                        if (strcmp(msg.user, "new client") == 0) {
                        switch (fork()) {
                                case -1:{
                                        perror("Error with fork");
                                        exit(1);
                                        }
                                case 0:{
                                        char gender[MAXLEN];
                                        char client_fifo[30];
                                        sprintf(msg.user, "I need client's gender\n");
                                        sprintf(client_fifo, "fifo_%d", msg.pid);
                                        msg.pid = getpid();
                                        int o;
                                        //open client's fifo for server to write to
                                        if ((o = open(client_fifo, O_WRONLY)) == -1) {
                                                        perror("Error opening client fifo");
                                                        exit(1);
                                                        }
                                        //send message
                                        write(o, &msg, sizeof(Message));
                                        //read client's answer, but program blocks here
                                        if ((read(f, &msg, sizeof(Message))) > 0) {
                                                sprintf(gender,"%s", msg.user);
                                                printf("Client's gender is %s\n", gender);
                                        }

                                        close(o);
                                        exit(0);
                                       }
                        }
                        }
                }
        }

        return 0;
}

The client code:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "header.h"
#include <unistd.h>

int f,fc;
char fifoname[20];
Message msg;

int main(int argc, char* argv[]) {

        sprintf(fifoname, "fifo_%d", getpid());
        if (mkfifo(fifoname, S_IFIFO | 0666) < 0) {
                perror("Error with client's fifo");
                printf("Could not create fifo_%d", getpid());
                exit(1);
        }
        if ((f=open(FIFONAME,O_WRONLY))<0) {
                perror("Error connecting to server");
                exit(2);
        }

        char gender[MAXLEN];
        strcpy(msg.user, "new client");
        msg.pid = getpid();
        //first message to server
        write(f, &msg, sizeof(msg));

        char arg[MAXLEN];
        if (argc > 1) {
                strcpy(arg, argv[1]);
        } else {
                strcpy(arg, "work");
        }
        if (strcmp(arg, "exit")) {

                if ((fc = open(fifoname, O_RDONLY))<0) {
                        perror("Error opening client's fifo");
                        printf("Could not open my fifo");
                        exit(3);
                }
                if (read(fc, &msg, sizeof(msg)) > 0) {
                        printf("%s\n",msg.user);
                }
                scanf("%s", gender);
                strcpy(msg.user, gender);
                msg.pid = getpid();
                printf("writing gender...\n");
                write(f, &msg, sizeof(msg));
                //program successfully reaches this print:
                printf("gender written\n");
                close(fc);
        }
        unlink(fifoname);
        close(f);
        exit(0);
}

And the header containing the struct for the message:

#define MAXLEN 20
typedef struct {
    int pid;
    char user[MAXLEN];
} Message;

#define FIFONAME "fifo_server"

I need to write further back and forth messages like this but I don't know how to get the server not to block on the second call of read()

Upvotes: 0

Views: 167

Answers (0)

Related Questions