?
Solved

How to use nonblocking socket?

Posted on 2005-03-04
13
Medium Priority
?
535 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 2
  • +1
13 Comments
 
LVL 84

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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
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

752 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