Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

How to use nonblocking socket?

Posted on 2005-03-04
13
Medium Priority
?
546 Views
Last Modified: 2008-02-01
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);
0
Comment
Question by:itcdr
  • 5
  • 4
  • 2
  • +1
12 Comments
 
LVL 85

Accepted Solution

by:
ozo earned 2000 total points
ID: 13463916
my @result;
for( 0..9 ){
   last if @result=$sock->getlines;
   sleep(1);
}
print "no response\n" unless @result;
0
 
LVL 1

Author Comment

by:itcdr
ID: 13464164
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
 
LVL 1

Author Comment

by:itcdr
ID: 13464679
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 16

Expert Comment

by:manav_mathur
ID: 13466869
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
 
LVL 1

Author Comment

by:itcdr
ID: 13466903
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
 
LVL 16

Expert Comment

by:manav_mathur
ID: 13467320
>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
 
LVL 20

Expert Comment

by:jmcg
ID: 13467476
Manav -

Note the line that begins with the keyword "last".
0
 
LVL 1

Author Comment

by:itcdr
ID: 13467508
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
 
LVL 16

Expert Comment

by:manav_mathur
ID: 13467712
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
 
LVL 1

Author Comment

by:itcdr
ID: 13467823
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
 
LVL 20

Expert Comment

by:jmcg
ID: 13469482
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
 
LVL 16

Expert Comment

by:manav_mathur
ID: 13474521
>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

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

577 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question