Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Another Unix Network Programming question!!! 1

Status
Not open for further replies.

aboujouj83

IS-IT--Management
May 9, 2003
52
US
This question is related to the one I asked before:
"I am reading unix netwrok programming volume 1 by stevens. It's a known book for network programming...."
I am still trying to understand well the code in figure 6.22 p166. There is one point that I still don't understand why is why the nready variable is decremented twice i.e once in line 43 and another time in line 58! I think that it should be only decremented once for each pass of the for(;;) loop.

Waiting for your clarification

Aboujouj
 
We are awake.

Why don't you post a question that contains enough information that we could answer it without having to go out and buy a book?

Also, if your question is specifically concerning the coding of the C source, then the C forum might be a better place to ask (assuming you supply a little code with your question).

Just a thought!

 
ok...this is the code:
(it is long though)


/* tcpsers1.cc */
/* tcpsers1.cc */
/* Figure 6.21 & 6.22 first half of tcpcliserv/tcpservselect01.c */
/* UNIX Network Programming - Sockets & XTI, W Richard Stevens */


/* include fig. 6.21 */
#include "unp.h"

int
main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char line[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;

listenfd = Socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);

Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

Listen(listenfd, LISTENQ);

maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);

/* end fig. 6.21 */




/* include fig. 6.22 Second half of tcpcliserv/tcpservselect01.c */
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef NOTDEF
printf(&quot;new client: %s, port %d\n&quot;,
Inet_ntop(AF_INET,&cliaddr.sin_addr,4, NULL),ntohs(cliaddr.sin_port));
#endif
for (i = 0; i < FD_SETSIZE; i++)
if (client < 0) {
client = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
err_quit(&quot;too many clients&quot;);
FD_SET(connfd, &allset);/*add new descriptor to set*/
if (connfd > maxfd) maxfd = connfd; /* for select */
if (i > maxi) maxi = I;/* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) {/* check all clients for data */
if ( (sockfd = client) < 0)
continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = Readline(sockfd, line, MAXLINE)) == 0) {
/*4connection closed by client */
Close(sockfd);
FD_CLR(sockfd, &allset);
client = -1;
} else
Writen(sockfd, line, n);
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
/* end fig. 6.22 */


I still don't understand why is why the nready variable is decremented twice (i.e we see twice --nready). I think that it should be only decremented once for each pass of the for( ; ; ) loop.

Waiting for your clarification

Aboujouj

Aboujouj

 
> nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
select() returns the number of descriptors which can be read

> if (FD_ISSET(listenfd, &rset)) { /* new client connection */
This is a special case, and can only decrement nready ONCE

> for (i = 0; i <= maxi; i++) {/* check all clients for data */
This checks all the descriptors and decrements nready for each one with data available
 
Thx Salem, very helpful post.
Now I have a question related to that: I have to use the code above but with some features added. One of them is the &quot;Private&quot; option:

&quot;If the optional, private argument is supplied, and no other client is already connected, the server will not allow other clients to join.&quot;

Server response: &quot;OK on success, ERR_PRIVATE if another client has invoked a private session, ERR_OTHERCLIENT if private is requested but another client is already connected.&quot;

What comes to my mind is to use the &quot;nready&quot; variable to check if any other client is connected before accepting a new connection requesting a &quot;private&quot; session. But this may not be the safest way, as a conneceted client can have a non-ready socket for a while.

Waiting for your suggestions

Aboujouj
 
> What comes to my mind is to use the &quot;nready&quot; variable to check if any other client is connected
nready only tells you which connections have data available, not which connections exist.

You need a separate variable called num_connections
and another variable called private_connected (a boolean)

For example, in the new connection part, you would have these tests
if num_connections > 0 AND private_requested - return ERR_OTHERCLIENT
if num_connections == 0 AND private_requested - return OK
if private_connected AND connection_requested - return ERR_PRIVATE
 
I am trying what you suggested, but I am having some problems with the private_requested variable: I know how to deal with the mun_connection variable because it acts only inside the server code, unlike the private_requested variable which needs to be handled in both the server and the client. I need some advice (pseudocode, example...) to understand this issue.
THANKS
Aboujouj

N.B: my server code is similar to the one provided above.

my client code is based on the following:

/*tcpcli01.cc */
/* Figure 5.4 & 5.5 tcpcliserv/tcpcli01.c and lib/str_cli.c */
/* UNIX Network Programming - Sockets & XTI, W Richard Stevens */

#include &quot;unp.h&quot;

int main(int argc, char **argv)
{ int sockfd;
struct sockaddr_in servaddr;

if (argc != 2)
err_quit(&quot;usage: tcpcli <IPaddress>&quot;);

sockfd = Socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

str_cli(stdin, sockfd); /* do it all */

exit(0);
}



void str_cli(FILE *fp, int sockfd)
{
char sendline[MAXLINE], recvline[MAXLINE];

while (Fgets(sendline, MAXLINE, fp) != NULL) {

Writen(sockfd, sendline, strlen(sendline));

if (Readline(sockfd, recvline, MAXLINE) == 0)
err_quit(&quot;str_cli: server terminated prematurely&quot;);

Fputs(recvline, stdout);
}
}
 
Hello Everybody,

I just went through this thread.
Can anybody provide me the soft copy of the book Unix Network Programming Vol I - by Stevens.
Unfortunately its not in book store here and I need it desperately.
Pls tell me on my personal id also if anybody can help me.
I will create the sufficient space in the account.

Thanx and Regards,
Saurabh

Email: agrsaurabh@hotmail.com

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top