read from a named pipe

10,878

There is a coding error in the server's while loop - the server will never exit the loop even when there is an error or the server receives eof on the FIFO. It should be changed to something like this:

while(1)
{
    if((bytesread = read( fd, buf, MAX_BUF - 1)) > 0)
    {
        buf[bytesread] = '\0';
        printf("Received: %s\n", buf);
    }
    else
        break;
}

Your other problem is that your client sends a single line and then closes the FIFO. The server reads until EOF. So it is going to read the single line, then hit EOF because the client closed. This is completely normal.

Where it becomes a problem is when you want your server to provide service to multiple clients. In that case you don't want to quit reading after every individual client closes its end. The semantics are such that the server will only see EOF after the last of all clients close. So an easy way to accommodate the server handling multiple clients is to open your server-side FIFO as read/write. Then there will always be a "writer", the server itself, with write end of the FIFO open. This will prevent the server from seeing EOF until you decide to shut it down.

A second problem is that you need to read and write in loops. You are not guaranteed to get your full data request filled in one call.

Also, having the client create the FIFO that the server reads is an odd approach. Normally you want the server to create a known FIFO to which clients connect.

Share:
10,878
Zagatho
Author by

Zagatho

Student

Updated on June 04, 2022

Comments

  • Zagatho
    Zagatho almost 2 years

    I have to implement a "printing server". I have 1 client file, and 1 server file:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int get_line( char *dest, int size );
    
    #define MAX 1024
    
    void main ()
    {
        char const *pipe = "printservers";
        char buffer[MAX];
        int fd;
    
        get_line( buffer, MAX );
    
        if( mkfifo( pipe, 0666 ) < 0 )
        {
            printf( "Cannot create a pipe\n" );
            exit( EXIT_FAILURE );
        }
    
        fd = open( pipe, O_WRONLY );
    
        write( fd, buffer, MAX );
    
        close( fd );
    
        //unlink( pipe );
    
    }
    
    int get_line( char *dest, int size )
    {
        int c, i;
        for( i = 0; i < size - 1 && ( c = getchar() ) != EOF && c != '\n'; ++i )
            dest[i] = c;
        if( c == '\n' )
        {
            dest[i] = c;
            ++i;
        }
        dest[i] = '\0';
        return i;
    }
    

    This is the client, which reads from the standard input a line and writes into a named pipe called printservers. This works as intended.

    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    #define MAX_BUF 1024
    #define MAX_PID 8
    
    int main()
    {
        int fd;
        char * myfifo = "printservers";
        char buf[MAX_BUF];
    
        /* open, read, and display the message from the FIFO */
        fd = open( myfifo, O_RDONLY );
        while( 1 )
        {
            if( read( fd, buf, MAX_BUF ) > 0 )
                printf("Received: %s\n", buf);
        }
        close(fd);
    
        return 0;
    }
    

    This is the server, which are read from the pipe. But it does not work with the while loop. If i send a message from the client, the first message is printed, but the following messages are ignored. Could somebody help me with my problem? Thanks Patrik

  • Zagatho
    Zagatho about 10 years
    Thanks Duck for your answer. If i use "write( 1, buf, size ), where size is the return value of read, only 1 character apears on the other terminal. If i use "write( 1, buf, BUFMAXSIZE ), it writes the message plus garbage ( some hiroglyphes ). Can you explain whats wrong?
  • Duck
    Duck about 10 years
    Not really without see what you are doing. I would suggest you write strlen bytes in the client not MAX bytes which going to write the string and whatever garbage in buf that follows it.
  • pilcrow
    pilcrow about 10 years
    Hmm, this isn't actually his problem (his non-problem)? The code posted doesn't terminate on EOF — it stays in a tight read() loop. As I comment above, I don't think we're seeing the actual and complete code.
  • Duck
    Duck about 10 years
    @pilcrow, you're right. I missed the while(1). I was focused on OP sending one msg per client. I'll amend the answer when I get a chance.