A question about read() from "Unix Network Programming", Vol 1
Web Server forum
Back To The Forum Home!Search!Private Messaging System

Web Server Talk Web Server Talk > Unix and Linux reviews > Free Unix support > Unix Programming > A question about read() from "Unix Network Programming", Vol 1




Pages (2): [1] 2 »   Last Thread   Next Thread Next
  Show Printable Version Email this Page Subscribe to this Thread      Post New Thread    Post A Reply      

    A question about read() from "Unix Network Programming", Vol 1  
K-mart Cashier


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-30-07 06:27 PM

The following code snippet is taken from figure 3.15 on page 89 from
the book "Advanced Unix Network Programming: The Sockets Networking
API", Vol 1, third edition,  by Stevens, Fenner, and Rudoff

1 #include     "unp.h"

2 ssize_t                         /* Read "n" bytes from a
descriptor. */
3 readn(int fd, void *vptr, size_t n)
4 {
5     size_t  nleft;
6     ssize_t nread;
7     char   *ptr;

8     ptr = vptr;
9     nleft = n;
10     while (nleft > 0) {
11         if ( (nread = read(fd, ptr, nleft)) < 0) {
12             if (errno == EINTR)
13                 nread = 0;      /* and call read() again */
14             else
15                 return (-1);
16         } else if (nread == 0)
17             break;              /* EOF */

18         nleft -= nread;
19         ptr += nread;
20     }
21     return (n - nleft);         /* return >= 0 */
22 }


On line 13, why is nread set to zero? Ie, why not just use a goto
statement?


Chad





[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
William Pursell


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 12:23 AM

On Dec 30, 7:16 pm, K-mart Cashier <cdal...@gmail.com> wrote:
> The following code snippet is taken from figure 3.15 on page 89 from
> the book "Advanced Unix Network Programming: The Sockets Networking
> API", Vol 1, third edition,  by Stevens, Fenner, and Rudoff
>
> 1 #include     "unp.h"
>
>  2 ssize_t                         /* Read "n" bytes from a
> descriptor. */
>  3 readn(int fd, void *vptr, size_t n)
>  4 {
>  5     size_t  nleft;
>  6     ssize_t nread;
>  7     char   *ptr;
>
>  8     ptr = vptr;
>  9     nleft = n;
> 10     while (nleft > 0) {
> 11         if ( (nread = read(fd, ptr, nleft)) < 0) {
> 12             if (errno == EINTR)
> 13                 nread = 0;      /* and call read() again */
> 14             else
> 15                 return (-1);
> 16         } else if (nread == 0)
> 17             break;              /* EOF */
>
> 18         nleft -= nread;
> 19         ptr += nread;
> 20     }
> 21     return (n - nleft);         /* return >= 0 */
> 22 }
>
> On line 13, why is nread set to zero? Ie, why not just use a goto
> statement?

In this case, a goto would work but is not necessary.
It is probably avoided for stylistic reasons only.





[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
K-mart Cashier


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 12:23 AM

On Dec 30, 12:40 pm, William Pursell <bill.purs...@gmail.com> wrote:
> On Dec 30, 7:16 pm, K-mart Cashier <cdal...@gmail.com> wrote:
>
>
> 
> 
> 
> 
> 
> 
>
> In this case, a goto would work but is not necessary.
> It is probably avoided for stylistic reasons only.


Okay, I was just curious because every once in a while when I ask
about a line of code, I'll get some kind of crazy response that is
written in academic jargon. Then when I ask for clarification, the
person will go off and cite some obscure part of the Unix Man pages.





[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
rumplstiltzkin@gmail.com


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 12:24 AM

Because code with goto's gets pretty nasty and hard to read quickly.

K-mart Cashier wrote:
> The following code snippet is taken from figure 3.15 on page 89 from
> the book "Advanced Unix Network Programming: The Sockets Networking
> API", Vol 1, third edition,  by Stevens, Fenner, and Rudoff
>
> 1 #include     "unp.h"
>
>  2 ssize_t                         /* Read "n" bytes from a
> descriptor. */
>  3 readn(int fd, void *vptr, size_t n)
>  4 {
>  5     size_t  nleft;
>  6     ssize_t nread;
>  7     char   *ptr;
>
>  8     ptr = vptr;
>  9     nleft = n;
> 10     while (nleft > 0) {
> 11         if ( (nread = read(fd, ptr, nleft)) < 0) {
> 12             if (errno == EINTR)
> 13                 nread = 0;      /* and call read() again */
> 14             else
> 15                 return (-1);
> 16         } else if (nread == 0)
> 17             break;              /* EOF */
>
> 18         nleft -= nread;
> 19         ptr += nread;
> 20     }
> 21     return (n - nleft);         /* return >= 0 */
> 22 }
>
>
> On line 13, why is nread set to zero? Ie, why not just use a goto
> statement?
>
>
> Chad





[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
Casper H.S. Dik


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 12:34 PM

K-mart Cashier <cdalten@gmail.com> writes:

>The following code snippet is taken from figure 3.15 on page 89 from
>the book "Advanced Unix Network Programming: The Sockets Networking
>API", Vol 1, third edition,  by Stevens, Fenner, and Rudoff

>1 #include     "unp.h"

> 2 ssize_t                         /* Read "n" bytes from a
>descriptor. */
> 3 readn(int fd, void *vptr, size_t n)
> 4 {
> 5     size_t  nleft;
> 6     ssize_t nread;
> 7     char   *ptr;

> 8     ptr = vptr;
> 9     nleft = n;
>10     while (nleft > 0) {
>11         if ( (nread = read(fd, ptr, nleft)) < 0) {
>12             if (errno == EINTR)
>13                 nread = 0;      /* and call read() again */
>14             else
>15                 return (-1);
>16         } else if (nread == 0)
>17             break;              /* EOF */

>18         nleft -= nread;
>19         ptr += nread;
>20     }
>21     return (n - nleft);         /* return >= 0 */
>22 }


>On line 13, why is nread set to zero? Ie, why not just use a goto
>statement?

While some people bend over backwards to avoid goto's, the other option
here would be to use "continue" to reenter the loop a the top.

(The one bug in the code here is that if initial reads succeed but a later
when fails, -1 is returned and not the number of bytes read)

I think it should be something more like:

if (errno == EINTR)
continue;
else if (nleft == n)
return (-1);
else
return (n - nleft);

Casper





[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
Rainer Weikusat


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 12:34 PM

K-mart Cashier <cdalten@gmail.com> writes:
> The following code snippet is taken from figure 3.15 on page 89 from
> the book "Advanced Unix Network Programming: The Sockets Networking
> API", Vol 1, third edition,  by Stevens, Fenner, and Rudoff
>
> 1 #include     "unp.h"
>
>  2 ssize_t                         /* Read "n" bytes from a
> descriptor. */
>  3 readn(int fd, void *vptr, size_t n)
>  4 {
>  5     size_t  nleft;
>  6     ssize_t nread;
>  7     char   *ptr;
>
>  8     ptr = vptr;
>  9     nleft = n;
> 10     while (nleft > 0) {
> 11         if ( (nread = read(fd, ptr, nleft)) < 0) {
> 12             if (errno == EINTR)
> 13                 nread = 0;      /* and call read() again */
> 14             else
> 15                 return (-1);
> 16         } else if (nread == 0)
> 17             break;              /* EOF */
>
> 18         nleft -= nread;
> 19         ptr += nread;
> 20     }
> 21     return (n - nleft);         /* return >= 0 */
> 22 }
>
>
> On line 13, why is nread set to zero? Ie, why not just use a goto
> statement?

Everything can be expressed in a multiplictly of different ways.
For this particular case,

ptr = vptr;
nleft = n;
while (nleft > 0) {
do
nread = read(fd, ptr, nleft);
while (nread == -1 && errno == EINTR);
if (nread <= 0) break;

nleft -= nread;
ptr += nread;
}

/* handle EOF or error */

would be the one I would be using nowadays, because it avoids playing
ugly games with state variables and 'using goto' at the same time.
A conditional jump backwards within the same block can always be
replaced by a 'proper' looping construct. Actually, I would prefer
a slight variation:

nleft = n;
ptr = vptr;
goto read;
do {
ptr += nread;

read:
do
nread = read(fd, ptr, nleft);
while (nread == -1 && errno == EINTR);
} while (nread > 0 && (nleft -= nread)):

And make it the responsibilty of the caller to only call
the function if it actually has something to do. Which is a nice of
example of a use of goto which can not be expressed
in C in a straightforward way.





[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
Giorgos Keramidas


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 12:34 PM

On Sun, 30 Dec 2007 11:16:23 -0800 (PST), K-mart Cashier <cdalten@gmail.com> wrote:
> The following code snippet is taken from figure 3.15 on page 89 from
> the book "Advanced Unix Network Programming: The Sockets Networking
> API", Vol 1, third edition, by Stevens, Fenner, and Rudoff
>
> 1 #include     "unp.h"
>
>  2 ssize_t                         /* Read "n" bytes from a
> descriptor. */
>  3 readn(int fd, void *vptr, size_t n)
>  4 {
>  5     size_t  nleft;
>  6     ssize_t nread;
>  7     char   *ptr;
>
>  8     ptr = vptr;
>  9     nleft = n;
> 10     while (nleft > 0) {
> 11         if ( (nread = read(fd, ptr, nleft)) < 0) {
> 12             if (errno == EINTR)
> 13                 nread = 0;      /* and call read() again */
> 14             else
> 15                 return (-1);
> 16         } else if (nread == 0)
> 17             break;              /* EOF */
>
> 18         nleft -= nread;
> 19         ptr += nread;
> 20     }
> 21     return (n - nleft);         /* return >= 0 */
> 22 }
>
>
> On line 13, why is nread set to zero? Ie, why not just use a goto
> statement?

So that lines 18 and 19 will have no effect on `nleft' and `ptr', and
the rest of the loop will fall back to the toplevel read() call.

I usually prefer writing a restart of read() in such cases slightly
differently:

while (nleft > 0) {
if ((nread = read(fd, ptr, nleft)) == -1) {
if (errno == EINTR)
continue;
return -1;

/* whatever */
}






[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
William Pursell


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 06:23 PM

On Dec 31, 8:50 am, Casper H.S. Dik <Casper....@Sun.COM> wrote:
> K-mart Cashier <cdal...@gmail.com> writes: 
<snip>[vbcol=seagreen]
> (The one bug in the code here is that if initial reads succeed but a later
> when fails, -1 is returned and not the number of bytes read)

The code works okay in the case of a successful initial
read followed by a subsequent failure.   I think
Casper's mis-reading shows that it is slightly convoluted
and could be cleaned up.






[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
Rainer Weikusat


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 06:23 PM

William Pursell <bill.pursell@gmail.com> writes:
> On Dec 31, 8:50 am, Casper H.S. Dik <Casper....@Sun.COM> wrote: 
> <snip> 
>
> The code works okay in the case of a successful initial
> read followed by a subsequent failure.   I think
> Casper's mis-reading shows that it is slightly convoluted
> and could be cleaned up.

if read returns -1, the condition on line 11 will be true, hence
line 12 is next, if errno now != EINTR, the next one will be
line 15, causing -1 to be returned.






[ Post a follow-up to this message ]



    Re: A question about read() from "Unix Network Programming", Vol 1  
William Pursell


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
12-31-07 06:23 PM

On Dec 31, 6:13 pm, Rainer Weikusat <rweiku...@mssgmbh.com> wrote:
> William Pursell <bill.purs...@gmail.com> writes: 
> 
>
> if read returns -1, the condition on line 11 will be true, hence
> line 12 is next, if errno now != EINTR, the next one will be
> line 15, causing -1 to be returned.

Which is correct behavior.





[ Post a follow-up to this message ]



    Sponsored Links  




 





   All times are GMT. The time now is 05:25 AM.      Post New Thread    Post A Reply      
Pages (2): [1] 2 »   Last Thread   Next Thread Next


Most Popular forums 

Forum Jump:
Rate This Thread:

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
 
Medical and Health forum | Computer Games Reviews | Graphics design forum

Back To The Top
Home | Usercp | Faq | Register