1

Hi there i am trying to make such a program in which the the two fds stdin and fifo monitor by select() and communicate with each other. select() will monitor either fifo ready for reading or stdin.

server.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/select.h>
int main(int argc,char *argv[]){
    int f,fifo_read,fifo_write,status;
    fd_set readset;
    FD_ZERO(&readset);
    char str[512]="start";
    if(argc !=2)
    if(argc != 2){
    printf("\nError: %s required argument [Fifo Name]\n\n",argv[0]);
            exit(EXIT_FAILURE);
    }

    if ((open(argv[1], O_RDWR)) < 0){
        f = mkfifo(argv[1],S_IRWXU);
        if(f<0){
            perror("Error While Creating FIFO ");
            exit(EXIT_FAILURE);
        }
        else
            printf("FIFO Created Successfully...\n");
    }

    while(strcmp(str,"end")!=0){
        fifo_write= open(argv[1],O_WRONLY);
        FD_SET(fifo_read, &readset);
        FD_SET(STDIN_FILENO, &readset);
        status = select(fifo_read+1, &readset, NULL, NULL, NULL);
        if(status==-1){
            perror("Error While Calling select() system call ");
            //exit(EXIT_FAILURE);   
        }
        if(FD_ISSET(STDIN_FILENO,&readset)){
            if(fifo_write<0)
                perror("\nError while writing on pipe ");
            else{
                printf("\nServer>> ");
                scanf("%s",str);
                write(fifo_write,str,strlen(str));
                close(fifo_write);
            }
        }
        fifo_read=open(argv[1],O_RDONLY);
        if(FD_ISSET(fifo_read,&readset)){
            if(fifo_read<0)
                perror("\nError while reading from pipe ");
            else{
                read(fifo_read,str,strlen(str));
                close(fifo_read);
                printf("\nJiya%s",str);
            }
        }
    }
    return 0;
}

client.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/select.h>
int main(int argc,char *argv[]){
    int f,fifo_read,fifo_write,status;
    fd_set readset;
    FD_ZERO(&readset);
    char str[512]="start";
    
    while(strcmp(str,"end")!=0){
        fifo_write= open(argv[1],O_WRONLY);
        FD_SET(fifo_read, &readset);
        FD_SET(STDIN_FILENO, &readset);
        status = select(fifo_read+1, &readset, NULL, NULL, NULL);
        if(status==-1){
            perror("Error While Calling select() system call ");
            //exit(EXIT_FAILURE);   
        }
        if(FD_ISSET(fifo_read,&readset)){
            if(fifo_read<0)
                printf("\nError opening read pipe");
            else{
                read(fifo_read,str,strlen(str));
                close(fifo_read);
                printf("\n%s",str);
            }
        }
        fifo_read=open(argv[1],O_RDONLY);
        if(FD_ISSET(STDIN_FILENO,&readset)){
            if(fifo_write<0)
                printf("\nError opening write pipe");
            else{
                printf("\nClient>> ");
                scanf("%s",str);
                write(fifo_write,str,strlen(str));
                close(fifo_write);
            }
        }
    }
    return 0;
}

Jamshid Ali
  • 101
  • 1
  • 11

2 Answers2

1

I have posted a working, somewhat simplified version of your code below. This code reads from STDIN in the client and sends that input through the pipe created by mkfifo to the server. The server loops reading from its end of the pipe and echoes what it read to STDOUT.

Client output:

CLIENT > Message1
CLIENT > Message2
CLIENT > Yet another message.
CLIENT > A fourth message, but this one is quite a bit longer than the first messages.
CLIENT > end

Server output:

SERVER: Got 8 byte message: 'Message1'                                                                      
SERVER: Got 8 byte message: 'Message2'                                                                      
SERVER: Got 20 byte message: 'Yet another message.'                                                         
SERVER: Got 77 byte message: 'A fourth message, but this one is quite a bit longer than the first messages.'
EOF encountered...                                                                                          

I'll highlight some of the main differences:

  • I first create the pipe special file via mkfifo in the server. I then open the special file in the server and the client. This happens before the loop, and the file descriptors stay open during the loop instead of being repeatedly opened and closed.
  • The client only writes to the pipe and the server only reads from the pipe. At least on Linux, pipes are unidirectional (pipe man page: Pipes and FIFOs (also known as named pipes) provide a unidirectional interprocess communication channel. A pipe has a read end and a write end...) Two pipes may be used for bidirectional communication on Linux, and even on systems that support bidirectional pipes, using two pipes would still be supported and would be more portable.
  • When calling read, you should use the total size of the str buffer, not strlen(str). Also, str should be cleared between reads, so as to not contain old data (memset in new code).
  • I used fgets instead of scanf.
  • After the server opens the FIFO, I unlink the file, so that it is automatically deleted from the file system. The underlying file object will still exist until processes using it have terminated. This is optional.

Server:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int fifo_read = -1;
    char str[512]= "";

    fd_set readset;
    FD_ZERO(&readset);

    if (argc != 2) {
        printf("Usage: %s FIFO_NAME\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* Server will make the FIFO, both sides will open it */
    if (mkfifo(argv[1], S_IRWXU) == -1) {
        perror("mkfifo()");
        exit(EXIT_FAILURE);
    }

    if ((fifo_read = open(argv[1], O_RDONLY)) == -1) {
        perror("open()");
        exit(EXIT_FAILURE);
    }

    if (unlink(argv[1]) == -1) {
        perror("unlink()");
        exit(EXIT_FAILURE);
    }

    while (1) {
        FD_SET(fifo_read, &readset);
        if (select(fifo_read + 1, &readset, NULL, NULL, NULL) == -1) {
            perror("select()");
            exit(EXIT_FAILURE);
        }

        if (FD_ISSET(fifo_read, &readset)) {
            ssize_t bytes_read;
            memset(str, 0, sizeof(str));
            bytes_read = read(fifo_read, str, sizeof(str));
            if (bytes_read == -1) {
                perror("read()");
                exit(EXIT_FAILURE);
            }
            else if (bytes_read == 0) {
                printf("EOF encountered...\n");
                break;
            }
            printf("SERVER: Got %ld byte message: '%s'\n", bytes_read, str);
        }
    }

    if (close(fifo_read) == -1) {
        perror("close()");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

Client:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int fifo_write = -1;
    char str[512] = "";

    fd_set readset;
    FD_ZERO(&readset);

    if (argc != 2) {
        printf("Usage: %s FIFO_NAME\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if ((fifo_write = open(argv[1], O_WRONLY)) == -1) {
        perror("open()");
        exit(EXIT_FAILURE);
    }

    while (1) {
        printf("CLIENT > ");
        fflush(stdout);

        FD_SET(STDIN_FILENO, &readset);
        if (select(STDIN_FILENO + 1, &readset, NULL, NULL, NULL) == -1) {
            perror("select()");
            exit(EXIT_FAILURE);
        }
        if (FD_ISSET(STDIN_FILENO, &readset)) {
            memset(str, 0, sizeof(str));
            if (!fgets(str, sizeof(str), stdin)) {
                printf("fgets() failed to read a line.\n");
                exit(EXIT_FAILURE);
            }

            // See https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input
            str[strcspn(str, "\r\n")] = 0;

            if (strcmp(str, "end") == 0) {
                break;
            }
            if (write(fifo_write, str, strlen(str)) == -1) {
                perror("write()");
                exit(EXIT_FAILURE);
            }
        }
    }

    if (close(fifo_write) == -1) {
        perror("close()");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}
mjbaker4
  • 46
  • 3
0

Here i Got the Solution :)

server.c

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

int main(int argc, char *argv[])
{
    if(argc != 2){
        printf("\nError: %s required argument [Fifo Name]\n\n",argv[0]);
        exit(EXIT_FAILURE);
    }
    int fd,wr,rd,ret;
    fd_set readset;
    if(mkfifo(argv[1],S_IRWXU)==-1){
        if(errno!=EEXIST)
            perror("Error unable to create FIFO ");
        else
            perror("Error unable to create FIFO ");
        exit(EXIT_FAILURE);
    }
    else
        printf("FIFO created Successfully!\n\n");
    fd = open(argv[1],O_RDWR);
    if(fd==-1){
        perror("Error Failed to open fifo\n");
        exit(EXIT_FAILURE);
    }
    while(!0){
        FD_ZERO(&readset);
        FD_SET(fd,&readset);
        FD_SET(STDIN_FILENO,&readset);
        sleep(1);
        ret = select(fd+1,&readset,NULL,NULL,NULL);
        if(ret==-1){
            perror("Error select() ");
            exit(EXIT_FAILURE);
        }
        char str[512]="";
        if(FD_ISSET(STDIN_FILENO,&readset)){
            //fprintf(stderr, ">> ");
            rd = read(STDIN_FILENO,str,sizeof(str));
            if(rd==-1){
                perror("Error while reading from fifo");
                exit(EXIT_FAILURE);
            }
            char temp[512]="Server :: ";
            strcat(temp,str);
            wr = write(fd,temp,sizeof(temp));
            if(wr==-1){
                perror("Error while writing to fifo ");
                exit(EXIT_FAILURE);
            }
            continue;
        }
        if(FD_ISSET(fd,&readset)){
            rd = read(fd,str,sizeof(str));
            if(rd==-1){
                perror("Error while reading from fifo");
                exit(EXIT_FAILURE);
            }else if(rd==0)
                continue;
            //fprintf(stderr,"P2: %s\n",str);
            printf("%s\n",str);
            //write(STDOUT_FILENO,str,sizeof(str));
        }
    }
}

client.c

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

int main(int argc, char *argv[])
{
    if(argc != 2){
        printf("\nError: %s required argument [Fifo Name]\n\n",argv[0]);
        exit(EXIT_FAILURE);
    }
    int fd,wr,rd,ret;
    fd_set readset;
    fd = open(argv[1],O_RDWR);
    if(fd==-1){
        perror("Error Failed to open fifo\n");
        exit(EXIT_FAILURE);
    }
    while(!0){
        FD_ZERO(&readset);
        FD_SET(fd,&readset);
        FD_SET(STDIN_FILENO,&readset);
        sleep(2);
        ret = select(fd+1,&readset,NULL,NULL,NULL);
        if(ret==-1){
            perror("Error select() ");
            exit(EXIT_FAILURE);
        }
        char str[512]="";
        if(FD_ISSET(fd,&readset)){
            rd = read(fd,str,sizeof(str));
            if(rd==-1){
                perror("Error while reading from fifo");
                exit(EXIT_FAILURE);
            }else if(rd==0)
                continue;
            //fprintf(stderr,"P2: %s\n",str);
            printf("%s\n",str);
            //write(STDOUT_FILENO,str,sizeof(str));
        }
        if(FD_ISSET(STDIN_FILENO,&readset)){
            //fprintf(stderr, ">> ");
            rd = read(STDIN_FILENO,str,sizeof(str));
            if(rd==-1){
                perror("Error while reading from fifo");
                exit(EXIT_FAILURE);
            }
            char temp[512]="Client :: ";
            strcat(temp,str);
            wr = write(fd,temp,sizeof(temp));
            if(wr==-1){
                perror("Error while writing to fifo ");
                exit(EXIT_FAILURE);
            }
            continue;
        }
    }
}

and the output is : OUTPUt

Jamshid Ali
  • 101
  • 1
  • 11