 |
|
 |
|
|
 |
A question about read() from "Unix Network Programming", Vol 1 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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 |
 |
 |
|
|
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. |
 |
|
|
 |
|
 |
|
|
 |
|
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
|
 |
|
 |
|