From: Daniel Berger Date: 2002-08-17T02:18:14+09:00 Subject: RFC: Net/Ping Hi all, This is a fairly simple Ruby version of 'ping', based somewhat on the Perl module of the same name. Please let me know what you think and if there are any obvious problems. I haven't implemented an ICMP ping yet, mainly because it's a pain and you have to be root to use it anyway. Any help in that area is appreciated, though. Oh, and before anyone complains about a lack of options, see "Unix Network Programming", p.661 and note the authors comments about "feature creep". :) Regards, Dan require "socket" require "timeout" module Net class Ping attr_accessor :host, :port, :time, :data, :exception def initialize(host,port=nil,time=5) @host = host @port = port || Socket.getservbyname("echo") @time = time @data = "ping" end end ########################################################################## # With a TCP ping, simply try to open a connection. If we are successful, # assume success. In either case, close the connection to be polite. ########################################################################## class PingTCP < Ping def ping begin timeout(@time){ begin t = TCPSocket.new(@host,@port) rescue @exception = $! t.close unless t.nil? return false else t.close return true end } rescue @exception = $! return false end end end ########################################################################## # With a UDP ping, send a simple text string and check the return string. # If they match, assume success. ########################################################################## class PingUDP < Ping def ping u = UDPSocket.open a = [] begin timeout(@time){ u.connect(@host,@port) u.send(@data,0) a = u.recvfrom(64) } if a[0] != @data return false end rescue @exception = $! return false else return true end end end ################################## # Use your system's ping command ################################## class PingExternal < Ping require "open3" def ping input, output, error = "" timeout(@timeout){ input,output,error = Open3.popen3("ping -c 1 #{@host}") } e = error.gets unless e.nil? @exception = e return false else return true end end end end =begin = Description net/ping - A simple version of "ping" using Ruby = Synopsis require 'net/ping' # check with udp or tcp ping t = Net::PingTCP.new(host) u = Net::PingUDP.new(host) e = Net::PingExternal.new(host) if t.ping puts "Host is alive" else puts "Couldn't connect to host: " + t.exception end = Ping Classes --- PingTCP Attempts to open a connection using TCPSocket. A successful open means the ping was successful. --- PingUDP Attempts to open a connection using UDPSocket and sends a small string. If the return string matches, the ping was successful. --- PingExternal Uses the 'open3' module and calls your system's local 'ping' command. If nothing is sent to stderr, the ping was successful. = Class Methods --- new(host,port=7,timeout=5) Creates a new Ping object of the appropriate type = Instance Methods --- ping Returns one of two values - true or false. If you want to know *why* it failed, you can check the 'exception' attribute. = Instance Attributes --- host Reset the host --- port Set the port number to open socket connections on. The default is 7 (or whatever your 'echo' port is set to). --- data The string sent in UDP connections. The default is "ping". --- timeout The amount of time before the timeout module raises a TimeoutError exception during connection attempts. --- exception If an exception is raised, it is caught and stored in this attribute. It is not raised in your code. = FAQ "Why don't you return exceptions if a connection fails?" - Because ping is only meant to return one of two things - success or failure. It's very simple. If you want to find out *why* the ping failed, you can check the 'exception' attribute. = Known Bugs None that I'm aware of. If you find any, please let me know! = Future Plans Add an PingICMP class (help wanted) = Author Daniel J. Berger djberg96 at hotmail dot com =end