Exceptions inside loops


#1

Hello all, quite new to ruby here.

I am trying to figure out how to catch exceptions and I am not having
luck.
Basically I have a script that loops over an array of ports and tries to
connect to see if there is a service running. If there is nothing
running
then I get a “Connection refused” error (ECONNREFUSED). In this case I
just
want to print a small message and move on to the next port, however, my
attempt at this just terminates the loop entirely. Here’s some
(simplified)
code:

begin telnetPorts.each do |port|
puts "Port " + port.to_s + “:”
t = TCPSocket.new(host,port)
banner = t.gets
t.close
end

rescue SystemCallError
puts "Unable to connect to port: " + $!
end

As it stands, this does catch the exception just fine, but moves to the
next
block of code immediately. I tried using ‘next’ but it is giving me an
error:
“unexpected next”. So how does one simply move on to the next port in
this
case? Do I need to rewrite it as a function?

Thanks for consideration,
-d


#2

darren kirby wrote:

begin telnetPorts.each do |port|
puts "Port " + port.to_s + “:”
t = TCPSocket.new(host,port)
banner = t.gets
t.close
end

rescue SystemCallError
puts "Unable to connect to port: " + $!
end

I believe you just need to move your exception handling inside the
each’s block

telnetPorts.each do |port|
begin
puts “Port #{port}:”
t = TCPSocket.new( host.port )
puts t.gets
t.close
rescue SystemCallError
puts “Unable to gonnect to port #{port}: #$!”
end
end


#3

quoth the Mike F.:

puts "Unable to connect to port: " + $!
t.close
rescue SystemCallError
puts “Unable to gonnect to port #{port}: #$!”
end
end

That did the trick, thank you.
Also thanks for for showing how to interpolate variables inside a
string.
I will get this with time…

Thanks again,
-d


#4

quoth the Dave B.:

end
t.close
exception handling like you’re doing here, but you can see that if an
puts “some exception was raised”
end

Now you can go back to your already-working solution from Mike
Fletcher’s post.

Cheers,
Dave

Thanks for the additional enlightenment Dave, I did see that syntax in
some
sample code but I was getting "Unexpected KRescue or somesuch error.
However,
now it is working as it should, and I just need to find out how to send
Socket a timeout (SO_RCVTIMEO seems not to be defined) but that is
another
post!

Thanks guys,
-d


#5

darren kirby wrote:

begin telnetPorts.each do |port|
puts "Port " + port.to_s + “:”
t = TCPSocket.new(host,port)
banner = t.gets
t.close
end

rescue SystemCallError
puts "Unable to connect to port: " + $!
end

I see the question has been answered; let me just explain a little
further.

Here’s the code you posted above with standard indentation:

begin
telnetPorts.each do |port|
puts "Port " + port.to_s + “:”
t = TCPSocket.new(host,port)
banner = t.gets
t.close
end
rescue SystemCallError
puts "Unable to connect to port: " + $!
end

The first “end” closes the do…end block given to the each method. The
second end closes the begin…end block. The rescue clause applies to the
begin…end block.

(Obviously) begin…end is used to introduce a new scope, often for
exception handling like you’re doing here, but you can see that if an
exception is caught, you end up outside the loop. If you added a “retry”
or “redo” to the rescue clause, you’d simply start the loop again from
the top.

You can add rescue clauses inside begin…end blocks and also def…end
method bodies:

def barf
raise “some exception”
rescue RuntimeError
puts “some exception was raised”
end

Now you can go back to your already-working solution from Mike
Fletcher’s post.

Cheers,
Dave