0

I am trying to connect a socket to a FIFO pipe, but can't find an easy way to do it.

At the moment I am using:

 char localbuf[2];

    while(1) {
            memset(localbuf,0,sizeof(localbuf));

            ret = read(sfd,localbuf,1);
            test(ret,"Unable to read from socket");

            ret = write(out,localbuf,1);
            test(ret,"Unable to write to out FIFO");

            read(in,localbuf,1);
            test(ret,"Unable to read from in FIFO");

            write(sfd,localbuf,1);
            test(ret,"Unable to write to socket");
    }

However, this seems horribly inefficient and wrong because it should not send the data until it receives a newline but cannot know beforehand how much data there will be.

Complete code here

Is there a better way?

Tookmund
  • 103
  • 1
  • 7
  • Please post a complete example. Why do you think that this is “horribly inefficient”? From what I can say now: why is your buffer only 2 bytes? That's certainly too small to be efficient. – 5gon12eder Feb 18 '15 at 21:27
  • Fixed my explanation. – Tookmund Feb 18 '15 at 21:31
  • How about using `fgets` or `getline`? You can `fdopen` a `FILE *` for any file descriptor. You can also `read` (or `recv`) into a *large* buffer and `memchr` for the `'\n'` yourself, if you really want to. The I/O functions will return early if not enough data is available. – 5gon12eder Feb 18 '15 at 21:35
  • `getline` looks like the best option ill try that – Tookmund Feb 18 '15 at 21:39

1 Answers1

1

Some hints to have a bigger throughput:

1) Set the non-blocking mode on file descriptors. Example here

2) Use "select" or "poll" to wait until data are coming in (many examples availabe, an explanation is here)

3) Enlarge the read buffers (e.g. up to 4 kb), so you can receive more data in a single call. Use the read's return value to know how many bytes you have actually received.

4) write the whole received buffer. Check write's return value to know how many bytes have been actually transferred, write may send less then you requested. In that case (probably congestion) send the remaining data later. "select" is able to signal you also if a fd is ready to be written. The whole logic becomes quite complicated, but if the throughput is your goal you probably have to deal with it.

5) Also, you can split your loop in two sepatare threads, one for the in->sfd direction and one for sfd->out direction. Many of the previous notes still apply.

Community
  • 1
  • 1
Giuseppe Guerrini
  • 4,274
  • 17
  • 32
  • Why set non-blocking mode? You normally want the read to block (and the write too). – Jonathan Leffler Feb 19 '15 at 20:48
  • The "waiting point" is on the "select" system call. When a channel gets ready to read (or write) the "read" call should not block so the loop may continue immediately handling more events. If read blocked, other events (e.g. Incoming data from the other direction) would be delayed. – Giuseppe Guerrini Feb 19 '15 at 20:59
  • I am unconvinced. The [`select()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html) specification says, in part: _A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. ... A descriptor shall be considered ready for writing when a call to an output function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully._ At least setting the O_NONBLOCK flag is unnecessary. – Jonathan Leffler Feb 19 '15 at 21:09
  • Nonblock avoids that reading n bytes blocks until exactly n bytes are received – Giuseppe Guerrini Feb 19 '15 at 21:16