Code Comments

Programming Forum and web based access to our favorite programming groups.
For Programmers: Free Programming Magazines | New: Database administration forum
Registration is free! Edit your profileCalendarFind other membersFrequently Asked QuestionsSearch -> 
Post New Thread











Thread
Author

Code snippet in UNPv1
Hello again comp.unix.programmer folks :).

I have been reading
UNIX Network Programming, Volume 1, Second Edition: Networking APIs:
Sockets and XTI, Prentice Hall, 1998, ISBN 0-13-490012-X.
<http://www.kohala.com/start/unpv12e.html>

In figure 16.3 the author has the following implementation of a
function called str_cli() which takes two arguments, a socket
descriptor and a file stream.
Because of the functions length, I'll just describe what I *think*
(because I'm not sure if I'm correct, thus why asking here) it does
wrong here.
The code in question is in nonblock/strclinonb.c, which you'll find in
<http://www.kohala.com/start/unpv12e/unpv12e.tar.gz> (226K)

It reads from the file stream and then writes to the socket descriptor
using FD_SET and select(). When the function encounters EOF in the
stream, it sends a FIN with shutdown() SHUT_WR, and keeps reading from
the socket until bytes read <= 0. It also uses some sort of buffering:
If data is available to be read from the stream, but the socket is not
ready to be sent data, it reads the data and adds it to the buffer.

The problem(s) are:

1) The way it uses the buffering looks like this
n = read(fd, bufptr, &buf[MAXLINE] - bufptr);
bufptr is a pointer to buf + the bytes already read. (it gets reset to
bufptr = buf when the bytes are sent to the socket)
Now, the code performs the following checks after that
if(n == -1) /* error unless errno == EWOULDBLOCK */
else if(n == 0) /* EOF */
else /* other stuff */
Now, n being 0 does not certainly mean the stream has reached EOF. It
could be that the buffer is full and &buf[MAXLINE] - bufptr equals 0.
read() when the third argument is 0 does nothing and returns 0.

2) The code doesn't even use the stream. Instead it uses STDIN_FILENO,
and the stream is not used at all!

I'd like to know what you think, and please if I'm blatantly
incorrect, don't flame much :).

Report this thread to moderator Post Follow-up to this message
Old Post
vippstar@gmail.com
03-24-08 12:23 AM


Re: Code snippet in UNPv1
> The problem(s) are:
>
> 1) The way it uses the buffering looks like this
> n = read(fd, bufptr, &buf[MAXLINE] - bufptr);
> bufptr is a pointer to buf + the bytes already read. (it gets reset to
> bufptr = buf when the bytes are sent to the socket)
> Now, the code performs the following checks after that
> if(n == -1) /* error unless errno == EWOULDBLOCK */
> else if(n == 0) /* EOF */
> else /* other stuff */
> Now, n being 0 does not certainly mean the stream has reached EOF. It
> could be that the buffer is full and &buf[MAXLINE] - bufptr equals 0.
> read() when the third argument is 0 does nothing and returns 0.

Can you quote the code you are talking about please ?
So far the for(;;) seems ok to me since bufptr == &buf[MAXLINE] will
never happen. The read is done only if it is part of the reading set.
And the fd is added to the set only if there is room in the buffer.
I may be wrong though, but since you did not quote any code ... ;-)

cheers,
-- paulo

Report this thread to moderator Post Follow-up to this message
Old Post
ppi
03-25-08 12:25 AM


Re: Code snippet in UNPv1
On Mar 24, 4:00 pm, ppi <vod...@gmail.com> wrote: 
> 
>
> Can you quote the code you are talking about please ?
Sure,

-- strclinonb.c --
/* include nonb1 */
#include	"unp.h"

void str_cli(FILE * fp, int sockfd)
{
int maxfdp1, val, stdineof;
ssize_t n, nwritten;
fd_set rset, wset;
char to[MAXLINE], fr[MAXLINE];
char *toiptr, *tooptr, *friptr, *froptr;

val = Fcntl(sockfd, F_GETFL, 0);
Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);

val = Fcntl(STDIN_FILENO, F_GETFL, 0);
Fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);

val = Fcntl(STDOUT_FILENO, F_GETFL, 0);
Fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);

toiptr = tooptr = to;	/* initialize buffer pointers */
friptr = froptr = fr;
stdineof = 0;

maxfdp1 = max(max(STDIN_FILENO, STDOUT_FILENO), sockfd) + 1;
for (;;) {
FD_ZERO(&rset);
FD_ZERO(&wset);
if (stdineof == 0 && toiptr < &to[MAXLINE])
FD_SET(STDIN_FILENO, &rset);	/* read from stdin */
if (friptr < &fr[MAXLINE])
FD_SET(sockfd, &rset);	/* read from socket */
if (tooptr != toiptr)
FD_SET(sockfd, &wset);	/* data to write to socket */
if (froptr != friptr)
FD_SET(STDOUT_FILENO, &wset);	/* data to write to stdout */

Select(maxfdp1, &rset, &wset, NULL, NULL);
/* end nonb1 */
/* include nonb2 */
if (FD_ISSET(STDIN_FILENO, &rset)) {
if ((n =
read(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0) {
if (errno != EWOULDBLOCK)
err_sys("read error on stdin");

} else if (n == 0) {
#ifdef	VOL2
fprintf(stderr, "%s: EOF on stdin\n", gf_time());
#endif
stdineof = 1;	/* all done with stdin */
if (tooptr == to)
Shutdown(sockfd, SHUT_WR);	/* send FIN */

} else {
#ifdef	VOL2
fprintf(stderr, "%s: read %d bytes from stdin\n",
gf_time(), n);
#endif
toiptr += n;	/* # just read */
FD_SET(sockfd, &wset);	/* try and write to socket below */
}
}

if (FD_ISSET(sockfd, &rset)) {
if ((n = read(sockfd, friptr, &fr[MAXLINE] - friptr)) < 0) {
if (errno != EWOULDBLOCK)
err_sys("read error on socket");

} else if (n == 0) {
#ifdef	VOL2
fprintf(stderr, "%s: EOF on socket\n", gf_time());
#endif
if (stdineof)
return;	/* normal termination */
else
err_quit("str_cli: server terminated prematurely");

} else {
#ifdef	VOL2
fprintf(stderr, "%s: read %d bytes from socket\n",
gf_time(), n);
#endif
friptr += n;	/* # just read */
FD_SET(STDOUT_FILENO, &wset);	/* try and write below */
}
}
/* end nonb2 */
/* include nonb3 */
if (FD_ISSET(STDOUT_FILENO, &wset) && ((n = friptr - froptr) > 0)) {
if ((nwritten = write(STDOUT_FILENO, froptr, n)) < 0) {
if (errno != EWOULDBLOCK)
err_sys("write error to stdout");

} else {
#ifdef	VOL2
fprintf(stderr, "%s: wrote %d bytes to stdout\n",
gf_time(), nwritten);
#endif
froptr += nwritten;	/* # just written */
if (froptr == friptr)
froptr = friptr = fr;	/* back to beginning of buffer */
}
}

if (FD_ISSET(sockfd, &wset) && ((n = toiptr - tooptr) > 0)) {
if ((nwritten = write(sockfd, tooptr, n)) < 0) {
if (errno != EWOULDBLOCK)
err_sys("write error to socket");

} else {
#ifdef	VOL2
fprintf(stderr, "%s: wrote %d bytes to socket\n",
gf_time(), nwritten);
#endif
tooptr += nwritten;	/* # just written */
if (tooptr == toiptr) {
toiptr = tooptr = to;	/* back to beginning of buffer */
if (stdineof)
Shutdown(sockfd, SHUT_WR);	/* send FIN */
}
}
}
}
}

/* end nonb3 */
-- strclinonb.c --

<snip>

Report this thread to moderator Post Follow-up to this message
Old Post
vippstar@gmail.com
03-25-08 12:25 AM


Re: Code snippet in UNPv1
>         FD_ZERO(&rset);
>         FD_ZERO(&wset);
>         if (stdineof == 0 && toiptr < &to[MAXLINE])
>             FD_SET(STDIN_FILENO, &rset);    /* read from stdin */
>         if (friptr < &fr[MAXLINE])
>             FD_SET(sockfd, &rset);  /* read from socket */
>         if (tooptr != toiptr)
>             FD_SET(sockfd, &wset);  /* data to write to socket */
>         if (froptr != friptr)
>             FD_SET(STDOUT_FILENO, &wset);   /* data to write to stdout */

Thanks for posting the code.
So yes, &buff[MAXLINE] will never be equal to buffptr in the read()
call.
The STDIN_FILENO and sockfd fds are not inserted in the list of fds to
be checked for incoming data i.e. buffer is full hence the reading
from these streams is delayed until the buffptr is updated i.e. some
data is sent.

So yes, 0 returned by read is really end of file.

cheers,
-- paulo

Report this thread to moderator Post Follow-up to this message
Old Post
ppi
03-25-08 12:25 AM


Re: Code snippet in UNPv1
On Mar 24, 5:44 pm, ppi <vod...@gmail.com> wrote: 
>
> Thanks for posting the code.
> So yes, &buff[MAXLINE] will never be equal to buffptr in the read()
> call.
> The STDIN_FILENO and sockfd fds are not inserted in the list of fds to
> be checked for incoming data i.e. buffer is full hence the reading
> from these streams is delayed until the buffptr is updated i.e. some
> data is sent.
>
> So yes, 0 returned by read is really end of file.
Ah yes, now I see it too, thanks a lot.

Report this thread to moderator Post Follow-up to this message
Old Post
vippstar@gmail.com
03-25-08 12:25 AM


Sponsored Links




Last Thread Next Thread Next
Search this forum -> 
Post New Thread

Unix Programming archive

Show a Printable Version Send to friend Email This Page to Someone! subscribe to this thread Receive updates to this thread
Computer Consultants
Programming Jobs
Visual Basic Controls
SQL Server Programming
Webservices
Java Security
Visual Studio
C# Programming
Visual J++
Software engineering
Open source Software
Perl Programming
PHP Programming
ASP Programming
ASP .NET Programming
Visual Basic Programming
Windows Scripting Host
Java Programming
Java Help
Java Beans
VBScript
Cobol
MAC Applications
Unix Programming
Forum Jump:
All times are GMT. The time now is 09:36 PM.

 
Free MCSE Braindumps | Real Estate Topics

Programming forum archive

Copyrights CodeComments.com 2004 - 2006

Powered by vBulletin Copyright 2000-2006 Jelsoft Enterprises Limited.