Unix Programming - The behavior of select

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > December 2006 > The behavior of select





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author The behavior of select
af300wsm@gmail.com

2006-12-18, 7:22 pm

Thanks for the advice with the first question of listening on two
sockets. I had forgotten that it was the accept call that blocked, not
listen. At any rate, now I've got a question about how select works.
In my program, I'm opening two sockets, one on IPv6 and the other on
IPv4 and listening. I highly doubt that I would get connect requests
from the two respective IP networks at the same time, but I thought I
should code for that contingency.

Basically, what I have is something like this:

int sockv4;
int sockv6;

fd_set sockets;
FD_ZERO( sockets );
FD_SET( sockv4, sockets );
FD_SET( sockv6, sockets );

while( 1 ) {
if( select( 2, &sockets, NULL, NULL, NULL ) == 0 ) {
processID = fork( );
switch( processID ) {
case 0:
FD_ZERO( sockets );
FD_SET( sockv4, sockets );
FD_SET( sockv6, sockets );
break;
case -1:
// handle the inability to fork problem
}
}

if( processID != 0 ) break;
}

if( FD_ISSET( sockv4, sockets ) ) {
// accept the IPv4 connection and process
} else {
// accept the IPv6 connection and process
}

Now the question is, given the way I've got this coded (in the case of
two connect requests at once), this will process the IPv4 request for
connect first. Would the IPv6 request actually trip up the select call
again since it's still there (it wasn't processed earlier), or is it
lost forever?

And, as I was writing this, I just thought of another problem. My code
above only considers connect requests as readable. In fact, any new
data arriving on the port will trip up the select call, so, how does
one distinguish between a connect request or just another set of data
to process? I'm wondering if this will be a problem or not. I just
remembered from the book, "UNIX Network Programming" that the return
value from accept is a new file descriptor. I'm saving that descriptor
in another class and not adding it to the file descriptor set. Thus,
the transactional data should not be a problem, correct?

Thanks,
Andy

Barry Margolin

2006-12-19, 1:31 am

In article <1166478474.977719.208080@l12g2000cwl.googlegroups.com>,
af300wsm@gmail.com wrote:

> Now the question is, given the way I've got this coded (in the case of
> two connect requests at once), this will process the IPv4 request for
> connect first. Would the IPv6 request actually trip up the select call
> again since it's still there (it wasn't processed earlier), or is it
> lost forever?


Nothing is lost. Select() doesn't tell you whether something has
happened, it tells you whether a call to a blocking function would have
returned if you called it instead of calling select(). As long as the
IPv6 socket is in a state where accept() would return, select() will
continue to report that it's ready.

> And, as I was writing this, I just thought of another problem. My code
> above only considers connect requests as readable.


You should actually use writefd's to check for connect requests. A
socket doesn't become readable until the other end sends some data.

> In fact, any new
> data arriving on the port will trip up the select call, so, how does
> one distinguish between a connect request or just another set of data
> to process?


If the socket is the one that you called listen() on, then it's a
connect request, since you can't transmit any data on this socket. If
it's a connected socket (one returned by accept()) then it's data to
process.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
af300wsm@gmail.com

2006-12-19, 1:23 pm


Barry Margolin wrote:
> In article <1166478474.977719.208080@l12g2000cwl.googlegroups.com>,
> af300wsm@gmail.com wrote:
>
>
> Nothing is lost. Select() doesn't tell you whether something has
> happened, it tells you whether a call to a blocking function would have
> returned if you called it instead of calling select(). As long as the
> IPv6 socket is in a state where accept() would return, select() will
> continue to report that it's ready.


Great! I was hoping that was the case.

>
>
> You should actually use writefd's to check for connect requests. A
> socket doesn't become readable until the other end sends some data.


Thank you. I wouldn't have thought that. I expected that the incoming
connect request was a readable event.

>
>
> If the socket is the one that you called listen() on, then it's a
> connect request, since you can't transmit any data on this socket. If
> it's a connected socket (one returned by accept()) then it's data to
> process.
>


Thanks. I realized, after reading further in "UNIX Network
Programming" (imagine that, reading further :-), that I was dealing
with different sockets/file descriptors. I didn't have to worry about
this.


Andy

Rainer Weikusat

2006-12-19, 1:23 pm

af300wsm@gmail.com writes:

[...]

>
> Thank you. I wouldn't have thought that. I expected that the incoming
> connect request was a readable event.


That is correct.

If the socket is currently listening, then it shall be marked
as readable if an incoming connection request has been
received, and a call to the accept() function shall complete
without blocking.
(SUS/ select)

If connect is called for a socket which has been switched to
nonblocking-mode, it will usually return -1 with errno == EINPROGESS
and using select (or poll) on this descriptor will indicate that it is
writeable once the connection has been fully established.
af300wsm@gmail.com

2006-12-19, 7:25 pm


>
> That is correct.
>
> If the socket is currently listening, then it shall be marked
> as readable if an incoming connection request has been
> received, and a call to the accept() function shall complete
> without blocking.
> (SUS/ select)
>
> If connect is called for a socket which has been switched to
> nonblocking-mode, it will usually return -1 with errno == EINPROGESS
> and using select (or poll) on this descriptor will indicate that it is
> writeable once the connection has been fully established.


Thank you for this explanation. It makes sense now.

Andy

bennett.tony@con-way.com

2006-12-19, 7:25 pm


af300wsm@gmail.com wrote:
> Thanks for the advice with the first question of listening on two
> sockets. I had forgotten that it was the accept call that blocked, not
> listen. At any rate, now I've got a question about how select works.
> In my program, I'm opening two sockets, one on IPv6 and the other on
> IPv4 and listening. I highly doubt that I would get connect requests
> from the two respective IP networks at the same time, but I thought I
> should code for that contingency.
>
> Basically, what I have is something like this:
>
> int sockv4;
> int sockv6;
>
> fd_set sockets;
> FD_ZERO( sockets );
> FD_SET( sockv4, sockets );
> FD_SET( sockv6, sockets );
>
> while( 1 ) {
> if( select( 2, &sockets, NULL, NULL, NULL ) == 0 ) {
> processID = fork( );
> switch( processID ) {
> case 0:
> FD_ZERO( sockets );
> FD_SET( sockv4, sockets );
> FD_SET( sockv6, sockets );
> break;
> case -1:
> // handle the inability to fork problem
> }
> }
>
> if( processID != 0 ) break;
> }
>
> if( FD_ISSET( sockv4, sockets ) ) {
> // accept the IPv4 connection and process
> } else {
> // accept the IPv6 connection and process
> }
>
> Now the question is, given the way I've got this coded (in the case of
> two connect requests at once), this will process the IPv4 request for
> connect first. Would the IPv6 request actually trip up the select call
> again since it's still there (it wasn't processed earlier), or is it
> lost forever?
>
> And, as I was writing this, I just thought of another problem. My code
> above only considers connect requests as readable. In fact, any new
> data arriving on the port will trip up the select call, so, how does
> one distinguish between a connect request or just another set of data
> to process? I'm wondering if this will be a problem or not. I just
> remembered from the book, "UNIX Network Programming" that the return
> value from accept is a new file descriptor. I'm saving that descriptor
> in another class and not adding it to the file descriptor set. Thus,
> the transactional data should not be a problem, correct?
>
> Thanks,
> Andy


Andy,

You may have already found it, but let me point out an what I believe
is an error in your example:

FD_ZERO( sockets );
FD_SET( sockv4, sockets );
FD_SET( sockv6, sockets );

while( 1 ) {
if( select( 2, &sockets, NULL, NULL, NULL ) == 0 ) {

You have hard-coded the first argument to select() as a 2...
The 1st argument to select(), as described in Steven's Unix Network
Programming
is:

"The maxfpd1 argument specifies the number of descriptors to be
tested. Its value is
the maximum descriptor to be tested plus one (hence our name
maxfdp1). The
descriptors 0, 1, 2, up through and including maxfpd1-1 are
tested."

So your "two socket select" example could be:

if ( select (max(sockv4, sockv6)+1, &sockets, NULL, NULL, NULL )
== 0 ) {

Your example would work if sockv4 & sockv6 are 0 & 1 or vice-versa.

-tony

af300wsm@gmail.com

2006-12-21, 1:20 pm


bennett.tony@con-way.com wrote:

> Andy,
>
> You may have already found it, but let me point out an what I believe
> is an error in your example:
>
> FD_ZERO( sockets );
> FD_SET( sockv4, sockets );
> FD_SET( sockv6, sockets );
>
> while( 1 ) {
> if( select( 2, &sockets, NULL, NULL, NULL ) == 0 ) {
>
> You have hard-coded the first argument to select() as a 2...
> The 1st argument to select(), as described in Steven's Unix Network
> Programming
> is:
>
> "The maxfpd1 argument specifies the number of descriptors to be
> tested. Its value is
> the maximum descriptor to be tested plus one (hence our name
> maxfdp1). The
> descriptors 0, 1, 2, up through and including maxfpd1-1 are
> tested."
>
> So your "two socket select" example could be:
>
> if ( select (max(sockv4, sockv6)+1, &sockets, NULL, NULL, NULL )
> == 0 ) {
>
> Your example would work if sockv4 & sockv6 are 0 & 1 or vice-versa.
>
> -tony


No, I hadn't gotten that far (mostly because I'm still coding, I
haven't actually compiled anything yet. Thank you for saving me some
time. I went and read through that section of the UNIX Network
Programming (I'm borrowing the book) and you're correct. I hadn't
actually read that far into the book yet.

Thanks again for saving me, what probably would have been a few hours
of debugging.

Andy

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com