How to use nonblocking socket?

Can you explain the use of non-blocking sockets in perl? In the following code I added 'Blocking=>0' and the result was the @result variable came out empty every time. If I remove 'Blocking=>0' the @result variable has the right data. Why?

$sock=IO::Socket::INET->new(Proto=>'tcp',PeerAddr=>"whois.crsnic.net:43",Timeout=>5,Blocking=>0);
$sock->print("domain $dm.$tld\n");
my @result=$sock->getlines;
close($sock);
LVL 1
itcdrAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ozoCommented:
my @result;
for( 0..9 ){
   last if @result=$sock->getlines;
   sleep(1);
}
print "no response\n" unless @result;
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
itcdrAuthor Commented:
AMAZING!!!! You just fixed most of my problems with that. My multithreaded whois app no longer freezes up. Thanks. Here is my final solution for geting the data.

my @result;
for(0..1)
{
   select(undef,undef,undef,0.2);
   last if @result=$sock->getlines;
}
error($sock,$dm,"No Response","Get",$x) unless @result;


Your result also fixed my problem for 2 other questions each worth 500 points:
1. http://www.experts-exchange.com/Programming/Programming_Languages/Perl/Q_21335562.html
2. http://www.experts-exchange.com/Programming/Programming_Languages/Perl/Q_21338525.html

Go ahead and post your answer at the other 2 questions to get more points.
0
itcdrAuthor Commented:
The answer to this question only answered part of question 1, so you can leave that one alone. However, it did fully answer question 2, so you can close that one. Sorry if I broke any rules. I wasn't expecting this answer to solve the other ones.
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

manav_mathurCommented:
In non-blocking types of socket, a read on the socket doesnt wait for the data to arrive on the socket. If data is not therem it will just return empty. In blocking types of sockets, a read on the file descriptor(describing the socket) blocks(i.e waits) until data arrives on the socket. Hence, if the data does not arrive(or is not scheduled to arrive), it will block indefinitely, making the script hang on the read.

The code above imposes a sort of a timeout on your read. It will try to read data every second for 10 seconds, and if it doesnt arrive, it will pront no-response.....needless to say, this will fall out on the very first iteration of the loop if the socket is in blocking mode.....as the very first read will itself wait for data to arrive on the socket. In blocking mode, this snippet, instead of imposing a sort of timeout, will force data to be rad from the socket 10 times......

maybe that clears up your doubts.........btw, it would help if you read up some C implementation of sockets....IO::Socket hides most of the implementation details from the user.....

Manav
0
itcdrAuthor Commented:
Thank for your help explaining how it works. I did read a little about blocking vs. non-blocking sockets and after your description I now understand completely. You'll notice that I changed the loop a little from:

my @result;
for( 0..9 ){
   last if @result=$sock->getlines;
   sleep(1);
}
print "no response\n" unless @result;

to:

my @result;
for(0..1)
{
   select(undef,undef,undef,0.2);
   last if @result=$sock->getlines;
}
error($sock,$dm,"No Response","Get",$x) unless @result;


After doing some tests I found that using ozo's loop every query executed atleast 1 sleep statement before getting the data. Also I found that any query that didn't get the data after the second sleep ended up with a no response. I also found that sleeping for an entire second was a waist of time. That's why I used the select statement to sleep for .2 seconds and you'll notice I placed the select statement before the check, which made everything run more effecient.
0
manav_mathurCommented:
>using ozo's loop every query executed atleast 1 sleep statement before getting the data
That doesnt appear to be the case, the code calls $sock->getlines before sleeping.....I dont think 'last' will make any further statements run inside the loop body....so if the very first $sock->getlines succeeds, the code won't sleep......

>Also I found that any query that didn't get the data after the second sleep ended up with a no response
Funny, the code says that it repeatedly calls $sock->getlines each second for 10 seconds before "No Responsing"ing out.....

Manav
0
jmcgOwnerCommented:
Manav -

Note the line that begins with the keyword "last".
0
itcdrAuthor Commented:
I understand that ozo's loop calls getlines before the sleep statement, but I found that every time the first getlines() statement failed so the loop continued with the sleep statement. That's why I moved the select statement before the getlines(). I found that by doing the following:

my @result;
for( 0..9 ){
   last if @result=$sock->getlines;
   print "$dm loop"; #I found that this print statement always printed atleast once. Which means the sleep statement will execute.
   sleep(1);
}
print "no response\n" unless @result;


You said, "I don't think 'last' will make any further statements run inside the loop body." That's only true if the getlines() statement succeeds, otherwise the loop continues. Note the 'last if'

I know that the code repeatedly calls getlines() each second for 10 seconds. What I am saying is that any time that the domain failed to getlines after the first 2 loops ended up with no response at the end. That's why I limited the loop to run only twice.
0
manav_mathurCommented:
jmcg,
>Note the line that begins with the keyword "last".
Can you elaborate what you are trying to point to?? I *am* seeing the last keyword. Thats what I told the author when I stated "I dont think 'last' will make any further statements run inside the loop body"......am I missing something here???

itcdr,
<quote>
 but I found that every time the first getlines() statement failed so the loop continued with the sleep statement. That's why I moved the select statement before the getlines().
</quote>
This will make the code wait before attempting even the first read on the socket.....

<quote>
That's only true if the getlines() statement succeeds, otherwise the loop continues
</quote>
That was the whole idea, wasnt it??

<quote>
 What I am saying is that any time that the domain failed to getlines after the first 2 loops ended up with no response at the end.
</quote>
Did you get on this as a hit-and-trial method?? Well....Ozo assumed 10, you check it out and decide on two, Im ok either ways ;)

0
itcdrAuthor Commented:
I know that placing the select statement before makes it wait before trying to getlines.  I tested it on 100 domains and the result was that the first time through the loop the getlines() statement failed, that's why I placed the select statement first. Wouldn't it be better to wait .2 seconds and try than to try knowing your going to fail and then wait .2 seconds? Also from that test of 100 domains I did find that any domain that had to go more than 2 loops ended up with a no response even if the domain had to go through 10 loops.
0
jmcgOwnerCommented:
Manav -

" In blocking mode, this snippet, instead of imposing a sort of timeout, will force data to be rad from the socket 10 times......"

I probably misinterpreted what you were trying to say here, since you had already said that the first read would block until data was available and thus terminate the loop.
0
manav_mathurCommented:
>In blocking mode, this snippet, instead of imposing a sort of timeout, will force data to be rad from the socket 10 times......

My fault....I said the right thing earlier but this statement is misleading.......

Manav
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.