2

I have been trying to read continuous data from a named pipe. But for some reason if I don't put a delay, the receiver will just stop reading and only a blank screen is shown after a few samples.

I need to send continuous data that might change in milliseconds, so that's why putting a delay wouldn't work. I am trying to simulate it first using a while loop (the real script will be reading financial data). This is my first attempt:

This is the sender, a python script:

import os
import time

try:
    os.remove("/tmp/pipe7")    # delete
except:
    print "Pipe already exists"
os.mkfifo("/tmp/pipe7")    # Create pipe
x = 0
while True:
    x = time.time()
    pipe = open("/tmp/pipe7", "w")
    line = str(x) + "\r\n\0"
    pipe.write(line)
    pipe.close()

    #time.sleep(1)


os.remove("/tmp/pipe7")    # delete

This is the receiver in C/C++:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>

#include <sys/stat.h>

#define MAX_BUF 1024


using namespace std;

int main()
{

    while(1){

        char buf[MAX_BUF];
        memset (buf, 0, sizeof(buf)); //Clearing the message buffer
        int fd = open("/tmp/pipe7", O_RDONLY);  // Open the pipe
        read(fd, buf, MAX_BUF);                         // Read the message - unblock the writing process
        cout << buf << endl;
        close(fd);                                 // Close the pipe

    }
    return 0;
}

What's wrong with my approach? And what's the best way to communicate continuously between the two programs using pipes?

Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
Luis Cruz
  • 1,488
  • 3
  • 22
  • 50
  • 3
    I wonder why you feel the need to open and close the pipe each time you read/write a line ? Maybe are you missing the `flush` method of the file object ? – Sylvain Leroux Apr 11 '15 at 22:57
  • 1
    @SylvainLeroux: It could definitely be the issue, because pipe logic is bound to available readers and writers. – myaut Apr 11 '15 at 22:59
  • I tried not closing the pipe everytime, and still doesn't seems to solve the issue. I don't have much experience with pipes or socket programming. So I'm having a hard time trying to figure out what's wrong. – Luis Cruz Apr 11 '15 at 23:05

1 Answers1

2

First, you don't need to open/close the pipe for each I/O operation. Eventually you might need to flush the output after each writing though.

Then, as you output line-based text data, you cannot really rely on a fixed width reading to get back your data. Given your example, I would simply read into a string -- and the istream should read up to the next blank (here \n\r)

All of this lead to something like that (untested -- beware of typos!):

with open("/tmp/pipe7", "w") as pipe:
    while True:
        x = time.time()
        line = str(x) + "\r\n"
        pipe.write(line)
        pipe.flush()
        # in real code, should somehow break the loop at some point

std::ifstream  pipe("/tmp/pipe7");  // Open the pipe
while(1){
    std::string istr;

    pipe >> istr;        
    cout << istr << endl;
    # In real code, should somehow break the loop at some point
}

close(fd);

operator >> is overloaded to read string from an istream. In that case, it will extracts characters from the stream and stop as soon as either a whitespace character is encountered or the end-of-stream is encountered. Broadly speaking, this allow to read back the input "word by word".

Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • Awesome, this works great. Could you elaborate on how to read the data in the pipe into a string though? The read() method doesn't accept a string right? – Luis Cruz Apr 11 '15 at 23:18
  • Nvm I just saw your edit with ifstream. Thank a lot, this is great!! Thank you. – Luis Cruz Apr 11 '15 at 23:23
  • Just one more question. Using the istream on this case wouldn't affect performance right? I see the data slows down by a lot when printing to the screen. – Luis Cruz Apr 11 '15 at 23:31
  • @Luis Just a random guess, maybe the "slowdown" is buffer-related. Try to [disable ifstream buffering](http://stackoverflow.com/a/16605541/2363712). – Sylvain Leroux Apr 11 '15 at 23:44