Exceptions To IO
 PickAxe Companion Notes

Peter Komisar      v.1.2.1               Conestoga College


reference: Programming Ruby 1.9, The Pragmatic Programmers Guide Thomas, Fowler & Hunt
http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy
Sockets programming in Ruby, IBM
https://www6.software.ibm.com/developerworks/education/l-rubysocks/l-rubysocks-a4.pdf
Tutorials Point, http://www.tutorialspoint.com/ruby/ruby_input_output.htm
RailsTips, http://railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/
Lee Java Wordpress, http://leejava.wordpress.com/2009/08/24/udp-client-and-server-in-ruby/
Tutorials Pointhttp://www.tutorialspoint.com/ruby/ruby_socket_programming.htm



Ruby and Java were both released in 1995. The authors
of these languages must have both been reading from the
same book with respect to exception handling. The models
used are quite similar though they use different keywords.
Ruby's model offers a few extra control options compared
to that of Java.


Errors Happen

Errors happen and need to be managed.  A typo that put
a letter into a number, a File constructor that opens on a
non-existent file or a 'divide by zero' are classic error
examples that need to be dealt with.

In the early days, error return codes were popularly used.
( i.e. HTTP 404 ) The Ruby interpreter is also an example
of this approach.


Ruby interpreter Normal Exit Code

Exit code: 0


The Exception Model: A Better Way


Packaging error conditions in Exception class objects, that
carry information about the error back to the user interface
provides a better way to handle errors. 


The Exception Class


Ruby, as in Java, has a root Exception class that acts as a
root for a large family of error conditions.  The following code

lists the Exception classes available in Ruby. The output has
been further formatted for added clarity.


Code Listing Ruby Exception Classes
// by Nick Sieger
http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy

exceptions = []
tree = {}
ObjectSpace.each_object(Class) do |cls|
  next unless cls.ancestors.include? Exception
  next if exceptions.include? cls
  next if cls.superclass == SystemCallError # avoid dumping Errno's
  exceptions << cls
  cls.ancestors.delete_if {|e| [Object, Kernel].include? e }.reverse.inject(tree) {|memo,cls| memo[cls] ||= {}}
end
indent = 0
tree_printer = Proc.new do |t|
  t.keys.sort { |c1,c2| c1.name <=> c2.name }.each do |k|
    space = (' ' * indent); space ||= ''
    puts space + k.to_s
    indent += 2; tree_printer.call t[k]; indent -= 2
  end
end
tree_printer.call tree

OUTPUT   // extra formatting added

BasicObject
 |_ Exception
      |_NoMemoryError
      |_ScriptError
      |   |_LoadError
      |   |_NotImplementedError
      |   |_SyntaxError
      |
      |_SecurityError
      |  
      |_SignalException
      |   |_Interrupt
      |      
      |_StandardError
      |   |_ArgumentError
      |   |_EncodingError
      |   |  |_Encoding::CompatibilityError
      |   |  |_Encoding::ConverterNotFoundError
      |   |  |_Encoding::InvalidByteSequenceError
      |   |  |_Encoding::UndefinedConversionError
      |   |  
      |   |_FiberError
      |   |_IOError
      |   |   |_EOFError
      |   |_IndexError
      |   |   |_KeyError
      |   |   |_StopIteration
      |   |
      |   |_LocalJumpError
      |   |_Math::DomainError
      |   |_NameError
      |   |   |_NoMethodError
      |   |  
      |   |_RangeError
      |   |   |_FloatDomainError
      |   |
      |   |_RegexpError
      |   |_RuntimeError
      |   |_SystemCallError
      |   |_ThreadError
      |   |_TypeError
      |   |_ZeroDivisionError
      |    
      |_SystemExit
      |_SystemStackError
      |_fatal

Choose 'Built in' or 'Custom'

The built in Exception classes are available for the Ruby programmer to use. The programmer can also extend StandardError or one of it's descendants to create custom exceptions. A class that extends StandardError inherits the error catching mechanisms by default. The following code opens a URL connection on IBM and redirects the contents to a file under the C drive.
Example
// adapted from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt require 'open-uri' web_page = open("http://www.ibm.com") output = File.open("c://ibm.html", "w") while line = web_page.gets output.puts line end output.close OUTPUT // see C drive
Look for ibm.html under C in a browser. It is probably
missing content but the idea is there. But What if A Problem Arises? Now had there been a download error it would be good to allow the program to make a graceful exit. Here is the related text example with exception handling in place. As in the text the key error handling words are highlighted. Example // adapted from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt require 'open-uri' page = "podcasts" file_name = "#{page}.html" web_page = open("http://pragprog.com/#{page}") output = File.open(file_name, "w") begin while line = web_page.gets output.puts line end output.close rescue Exception STDERR.puts "Failed to download #{page}: #{$!}" output.close File.delete(file_name) raise end Following is the form of the exception handling blocks. In addition to the keywords shown in the above example there is a optional else clause that may be included. Exception Handling Block begin # protected code rescue # error handling retry
# used to rerun block on a condition else # no error comment ensure # always executes regardless end
Begin Block Parts
It is hard to resist comparing to Java.


Ruby & Java's Exception Handling Compared

Ruby Keywords

Java Keywords

 begin

 try

 rescue

 catch

 else

 ------

 retry

 -----

 ensure

 finally


Ruby uses the begin block to house code that might
throw an exception, and within it, the rescue clause to supply a response if an exception occurs. The else clause acts as a 'no problem' reporter. The ensure clause is an 'always execute' section that runs whether an exception is thrown or not. The Global Variable $! Holds a Reference to Raised Exception When an exception is raised a reference to it is placed into the global variable $!. A raise without parameters will re-raise the exception referenced in $1. This technique facilitates passing on exceptions that have not been handled. To demonstrate this consider the classic 'divide by zero' error, caught in the following example. Divide by Zero Error Capture Example begin 1 / 0 # the old divide by zero rescue puts "It's a zero divide" print "What is $! holding? --> " , $!,"\n" else puts "This isn't going to make the console! " ensure puts " Is there something that has to be done?" end OUTPUT It's a zero divide What is $! holding? --> divided by 0 Is there something that has to be done? In the above example the default Exception super 'catch all' class is implicitly specified. Specifying Exception Types "With Multiple Rescue Clauses The following example shows you can have multiple rescue blocks. In each of these rescue clauses a particular exception is specified. The rescues are tested in turn and the first match is executed. Here the second one is executed. If no match is found the exception is raised outside the block. Example begin 1/0 # the old divide by zero rescue TypeError puts "RESCUE 1" print "Exception Type --> " , $!,"\n" rescue ZeroDivisionError puts "RESCUE 2" print "Exception Type --> " , $!,"\n" end OUTPUT RESCUE 2 Exception Type --> divided by 0 The effect of the raise statement can be seen in the output where the exit code changes from the normal zero to having the exception forwarded to the console from main. // described in text as 're-raising the exception in $! Effect of the Unparamaterized rescue Statement begin 1/0 # the old divide by zero rescue ZeroDivisionError # raise end OUTPUT // without raise Exit code: 0 OUTPUT // commenting the raise in exception.rb:2:in `/': divided by 0 (ZeroDivisionError) from exception.rb:2:in `<main>' >Exit code: 1 Naming the Raised Exception The following example shows a variable can be introduced to provide a name tag for the exception that is thrown. Example begin 1/0 # the old divide by zero rescue ZeroDivisionError=>zeroDiv puts zeroDiv end The retry Keyword The retry keyword can be used to rerun the block given a certain condition. See text for an example. The reader is warned of the obvious potential of generating infinite loops. System Errors "System errors are raised when a call to the operating system returns an error code. " - PickAxe " Module Errno is created dynamically to map these operating
system errors to Ruby classes,
with each
error number generating
its own subclass of
SystemCallError. As the subclass is created
in module
Errno, its name will start Errno::. " -Ruby Docs
Following are some examples and their numeric values.
Example puts Errno::EACCES::Errno puts Errno::EAGAIN::Errno puts Errno::EPERM::Errno puts Errno::EIO::Errno puts Errno::EWOULDBLOCK::Errno puts Errno::EINTR::Errno
OUTPUT
13 11 1 5 10035 4 The raise Keyword, Raising Your Own Exceptions Exceptions can be generated using the raise keyword. This is analogous to how the 'throw' keyword is used in Java. Just running the word, raise in Ruby shows an unhandled exception has occurred. Example raise OUTPUT exception.rb:1:in `<main>': unhandled exception >Exit code: 1 If a string is associated with 'raise', a new Runtime exception is created with that comment associated with it. Example raise "Exception Taken" OUTPUT exception.rb:1:in `<main>': Exception Taken (RuntimeError) >Exit code: 1 The begin block can be added to handle an exception that was raised explicitly. Example begin raise "Exception Taken" rescue puts " There was an exception but it OK! " end OUTPUT There was an exception but it OK! >Exit code: 0 Creating a Custom Exception Subclass Exceptions can be created by extension to suit a particular need as is shown in the following example. Example class LogicalException < StandardError attr :message def initialize(message) @message = message end end begin if (true) raise LogicalException.new("The \'I always lie\' Paradox") end rescue LogicalException=> er puts er.message end OUTPUT The 'I always lie' Paradox The catch and throw Control in Ruby The catch and throw mechanism is really more a flow control mechanism than part of Ruby's exception handling mechanism. It does not in action parallel the similarly named keywords in Java. The catch is used to set up a block within which the throw statement can be used to abandon operation of that block under a given set of conditions. The catch .. throw Form catch ( :label, 2nd_arg_return_ val ) { throw :label } Example catch (:done) do x=0 2.times{x+=1; puts "Doing Stuff"} puts x if (x>=2) # increase 'trip value' to 3 and throw won't execute throw :done end 2.times{puts "Doing More Stuff But ..."} end OUTPUT Doing Stuff Doing Stuff 2 Directing Control To an Higher Scope The label can be used to direct the resumption of code to a catch in higher scope as is shown in the following example. ( change the label associated with the throw clause to see the different effect on flow control. Example catch(:outer){ puts "before inner catch" catch (:inner) { puts "before inner label" throw :outer # change to outer puts "after inner label" } puts "after inner catch" } OUTPUT before inner catch before inner label after inner catch Return Value The catch returns nil unless the throw is accompanied by a second parameter which becomes the return value as is shown in the example below. Example ans = catch (:inner) { throw :inner, "inner peace" } string = "Sometimes you can be thrown but still find #{ans}." puts string OUTPUT Sometimes you can be thrown but still find inner peace. Using throw & catch in Some Form of Validation The following example from the text shows a throw and catch combo being used to terminate a program if a specific character is entered, here an exclamation mark. Example // adapted from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt def prompt_and_get(prompt) print prompt res = readline.chomp throw :quit_requested if res == "!" res end catch :quit_requested do name = prompt_and_get("Name: ") age = prompt_and_get("Age: ") sex = prompt_and_get("Sex: ") # .. # process information end produces => an early termination if ! mark is entered

IO



Much IO capacity is defined in the Kernel module. The
Kernel module is 'mixed in' to Object class and so it's
methods are globally available to all classes as all classes
descend from Object.


"Object mixes in the Kernel module, making the built-in
kernel functions globally accessible. "
- Ruby Docs

The following summary of the Kernel methods shows that
a great
deal of the capability we have been introduced to
so far in Ruby is
defined in the Kernel module, which in turn
is part of the Object class.



Kernel Method Summary

Array Complex Float Integer Rational String __callee__ __method__ ` abort at_exit autoload autoload? binding block_given? callcc caller catch chomp chop eval exec exit exit! fail fork format gets global_variables gsub iterator? lambda load local_variables loop open p print printf proc putc puts raise rand readline readlines require select set_trace_func sleep spawn sprintf srand sub syscall system test throw trace_var trap untrace_var warn



Following are some of the IO methods from Kernel that we have
used ( and some others that have yet to be introduced)



Common IO Methods Defined in Kernel


The output methods we are use to using might be
prefixed with Kernel.

Example

print  "The puts( ) method is the same as "
Kernel.puts "Kernel.puts( )"

OUTPUT

The puts( ) method is the same as Kernel.puts( )


The Specialized IO Class

IO, standing for Input and Output, is an object that you
read from or write to.

Ruby's IO hierarchy is relatively simple with a base IO
class providing parentage for File and BasicSocket
classes.


IO Hierarchy

    IO
     |_File
     |_BasicSocket


Socket Classes Used for Networking

BasicSocket is in turn the parent of a set of classes
specialized to make network connections.

Socket Hierarchy

BasicSocket
        |     
        |_Socket
        |_IPSocket
        |       |_UDPSocket
        |       |_TCPSocket
        |                     |_TCPServer
        |
        |_UNIXServer
        |          |_UNIXServer
        |      
        |_SocketError       

// there is an Addrinfo class in the package as well


The File Class

The first thing that is done with a file is to open
it. Eventually you will also need to close it. This
action is encapsulated in the File constructor.


Example
// File opens in default read mode

file = File.new("Milton")
# process file
file.close

# same as

file = File.new("Milton", "r")
# process file
file.close

Following are different modes available.

Ruby Read Write Modes      // adapted from Tutorial Points,
  
http://www.tutorialspoint.com/ruby/ruby_input_output.htm

Modes

Description

 r

Read-only, the default. The file pointer is at the beginning of the file.

 r+

Read-write mode. The file pointer is at the beginning of the file.

 w

Write-only, overwrites file if it exists. If not, creates a new writeable file

 w+

Read-write, overwrites file if it exists. If not creates a new read-write file

 a

Write-only mode. The file pointer is at the end of the file if it exists and is in append mode. If the file does not exist, it creates a new file for writing.

 a+

Read and write mode. The file pointer is at the end of the file if it exists  in append mode. If the file does not exist, it creates a new read-write file


These values can also be represented by the following constants.
For the complete list see page 506, in Programming Ruby 1.9x.


Read Write Mode Constants
  // see page 506, PickAxe


Example

file = File.new("Milton.txt", File::APPEND)
 
file.close


File.open and File.new

File.open opens a file just as File.new does. If a block
is supplied to File.open, the opened file is passed to
the block as a parameter. When the block returns the
file is closed, even if an exception is raised within the
block.

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

File.open("testfile", "r") do |file|
# ... process the file
end #
<- file automatically closed here

With File.new closing the file is your responsibility,
This would typically be done in an 'ensure' clause
clause of a begin block.


The gets( ) Method

The gets( ) method reads a line from the file object.


Example


file = File.new("Milton.txt", "r+")
first_line = file.gets
puts first_line
file.close

OUTPUT

"Paradise Lost is an epic poem in blank verse by the 17th-century English poet John Milton.

We saw earlier the form of the while statement that
allows reading the whole file. It is nice as the gets( )
method runs until it returns nil which breaks the while
loop.


Example

while line = gets
puts line
end

Adding the loop to the above example yields the following.


Example


file = File.new("Milton.txt", "r+")
while line = file.gets
puts line
end
file.close

OUTPUT

"Paradise Lost is an epic poem in blank verse by the 17th-century English poet John Milton.
It was originally published in 1667 (though written nearly ten years earlier) in ten books, with
a total of over ten thousand individual lines of verse. A second edition followed in 1674,
redivided into twelve books (in the manner of the division of Virgil's Aeneid) with minor
revisions throughout and a note on the versification; the majority of the poem was written
while Milton was blind, and was transcribed for him." - wikipedia



Reading Iterators


In the next example, from the text,  the each_byte( ) method
reads off  8-bit bytes. Indexes are used to decide how many
characters are processed. The block processes the output
to ASCII characters plus it's integer value. 

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

File.open("testfile") do |file|
file.each_byte.with_index do |ch, index|
print "#{ch.chr}:#{ch} "
break if index > 10
end
end

produces:

T:84 h:104 i:105 s:115 :32 i:105 s:115 :32 l:108 i:105 n:110 e:101



The dump( ) Method


String has a dump method which works with lines to reveal
newline characters. Notice it does not reveal the other escapes
included.
To focus attention on the method, the example is simply
executed
on a string.


Example


string = "\n The string with \'newlines\' \n"
puts string
puts string.dump

OUTPUT

 The string with 'newlines'
"\n The string with 'newlines' \n"


Using Characters as Line Separators

The character that is used to delineate lines can
be arbitrarily set via the each_line( ) method as
is shown in the following. Some text is supplied
for the file.  The line separator selected is the
vertical bar
.

Sample Text For a Test File    // save as 'night'

The night is long. | I have been waiting since seven. |
There is not a Tim Horton's here. | Worse, I gave up drinking coffee.|
Tic! Toc! Goes the clock! |


Example


File.open("night") do |file|
file.each_line("|") {|line| puts  line.dump }
end
 
OUTPUT

"The night is long. |"
" I have been waiting since seven. |"
"\nThere is not a Tim Horton's here. |"
" Worse, I gave up drinking coffee.|"
"\nTic! Toc! Goes the clock! |"
"\n"


The for_each Method


" If you combine the idea of an iterator with the auto-closing
block feature, you get IO.foreach.
This method takes the name
of an I/O source, opens it for reading, calls the iterator once for

every line in the file, and then closes the file automatically: "
                                                             - Programming Ruby 1.92


This is shown in the following text example.

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt
IO.foreach("testfile") {|line| puts line }

produces:

This is line one
This is line two
This is line three
And so on...


Putting a File's Content Into a String


Ruby makes it simple to put the entire contents of a
file into a string as shown in the next example.

s = IO.read("Milton.txt")
puts s.length
puts s

OUTPUT  // condensed 

"Paradise Lost is an . . .  transcribed for him."             - wikipedia


Putting a Files Content Into an Array Using readlines( )

IO class has a readlines( ) method that is useful for
changing the contents of a file to an array where each
element of the array holds a line. 


arr = IO.readlines("testfile")
arr.length # => 4
arr[0] # => "This is line one\n"
# results in an array with one line per element

OUTPUT   // last line condensed

4
the majority of the poem . . . was transcribed for him." - wikipedia



Writing to File


The following is an example of appending a comment to
the
Milton file.

Example

File.open("milton.txt", "a") do |file|
file.puts "\n\n Comments \n\n"
file.puts "Really enjoyed the blurb on Milton - Tony Mills"
end

OUTPUT  // See the milton text file


Behind The Scenes With the puts( ) and print( ) Methods

When an object is being put to console with one these output
methods normally the to_s( ) method is called on the object.
If nothing meaningful is defined for to_s( ), the the objects UID
is printed to screen.

Two Special Cases // using puts

Example

array =[ :a, :b, :c]
puts array
puts  nil
puts  "A_line_under_an_empty_string"
# puts nil outputs an empty string

OUTPUT
a
b
c

A_line_under_an_empty_string


Writing Binary Into a String


The text shows a number of ways to do this in it's
example.

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

str1 = "\001\002\003" # => "\x01\x02\x03"

str2 = ""
str2 << 1 << 2 << 3 # => "\x01\x02\x03"
[ 1, 2, 3 ].pack("c*") # => "\x01\x02\x03"


Appending to Standard Output


The text has the following interesting example.

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

endl = "\n"
STDOUT << 99 << " red balloons" << endl

OUTPUT

99 red balloons


The << , Left Shift Operator
//  the append operator 

It is noted that the append operator is very handy as it
is overridden for different object types. It therefore
can
be used without a lot of concern if it adds to an array,

file or string. This makes it good for testing.


The StringIO Class


At this point the text introduces us to the StringIO class.
The documentation for the class, is very scant,  offering
only that it allows 
"pseudo I/O on a String object". 

The class is the only resident of the 'stringio' package so to
use it, this package is required.

The class allows a string to be treated in a manner similar
to a file.

The example, modified slightly from the text,  shows us this
approach.

Example // adapted from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

require 'stringio'

ip = StringIO.new("Now is\nthe time\nto learn\nRuby!\n\n")
op = StringIO.new("", "w")
ip.each_line do |line|
op.print line.reverse
end
print op.string


OUTPUT

si woN
emit eht
nrael ot
!ybuR


Networking IO   
// Class details are supplemental and are not required learning

Ruby supplies all the classes one needs to develop networking
programs. Networks are based on connections which in turn
are implemented in socket technology, originally developed
at Berkley in the 80s.

// with 4.2BSD Unix operating system, released in 1983

Following are the Networking Subclasses of BasicSocket with
a brief description of what they do.

Socket Classes With Descriptions


SOCKS

A protocol for handling TCP traffic through a proxy server. It can be used with virtually any TCP application, including Web browsers and FTP clients. It provides a simple firewall because it checks incoming and outgoing packets and hides the IP addresses of client applications.                                                      -Webopedia

  http://www.webopedia.com/TERM/S/SOCKS.html



INSERT: Class Methods in Ruby

The IBM paper referenced in this note uses the double colon
notation, :: to reference class methods. We have to this point
only been instructed to use this notation in referencing variables
defined in modules. Following is the notation used to describe
a Socket class method in the IBM Networking paper.


Example


Socket
::gethostname

Fortunately in testing, the form of referencing a  class method
via the class name and the dot operator also works. Following
is an example
from the IBM paper run using irb.

Example

>irb
irb(main):001:0> require 'socket'
=> true
irb(main):003:0> IPSocket::getaddress('www.ibm.com')
=> "129.42.56.216"

The next example shows we can sub in the single dot reference
form.



Example showing dot Notation Working as Well

irb(main):004:0> IPSocket.getaddress('www.sentex.net')
=> "98.159.240.6"

How to Create Class Methods

The following example from the 'RubyTips's site shows class
methods are created by defining them explicitly using the 'self'
keyword.

Defining Class Methods Example // from RubyTips, see url above


class Foo
  def self.bar
    puts 'class method'
  end
 
  def baz
    puts 'instance method'
  end
end

Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class

Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar’



Taking the lead from the IBM paper, details are provided
for the more common classes of the collection, namely
Socket, UDPSocket, TCPSocket and TCPServer. 

// you might want to add IPSocket


Socket Class


The Socket class is encapsulates the BSD Sockets API. Standard
functions include accept, bind, listen and connect among others.


Socket Constructor


Following is a partial list of methods.


Socket Class Methods
// prefix methods in use as in Socket::for_fd(fd)


Socket Instance Methods


UDPSocket


The UDPSocket class implements the connectionless User
Datagram Protocol.
UDP is used in the Domain Name Service
(DNS) protocol, the Dynamic Host Configuration Protocol
(DHCP), the Service Location Protocol (SLP), the Network
Time Protocol (NTP), and the Trivial File Transport Protocol
(TFTP).


UDP is fast as it is does not guarantee receipt of data as does
TCP. It is 
good for services that merely retransmit after a certain
time out. 


UDPSocket Constructor


UDP Instance Methods


The examples show how remarkably brief the code is to create
clients and servers.  This example is quite simple, yet it does
speak to the power of Ruby to do things in a succinct manner.

Run the following  on separate DOS terminals starting the server
first. Watch the Server window as you start the client. It signals
the server 5 times before the server retires. 


Example
// from LeeJava Wordpress,
http://leejava.wordpress.com/2009/08/24/udp-client-and-server-in-ruby/


Server Example

require 'socket'
    s = UDPSocket.new
    s.bind(nil, 1234)
    5.times do
      text, sender = s.recvfrom(16)
      puts text
    end


Client Example

require 'socket'
s = UDPSocket.new
s.send("hello", 0, 'localhost', 1234)


TCPSocket and TCPServer classes

The TCP Transmission Control Protocol is described as a
connection-based, and 'reliable' Transmission Control Protocol.
It goes one step beyond UDP in providing a guarantee that
data is received by the target receiver.

While UDP is like regular mail, TCP is more like registered mail.
 
This all comes from fact that in TCP a sender of a data packet
waits to be notified that the packet has been received by the
recipient. If the acknowledgment isn't received, the data is
sent again.
 
The TCPSocket class supports the 'reliable' Transmission Control
Protocol. A helper class for the creation of TCP server sockets
is also available in the TCPServer class


TCPSocket and TCPServer Constructors



TCPSocket and TCPServer Instance Methods


The following is a simple TCP Client Server Example where
the server sends the client the time. Run the server first in one
DOS window.

TCP Server Example
// adapted from example at Tutorial Points, see references for URL
require 'socket'             
server = TCPServer.open(23456)
loop {                      
  client = server.accept    
  client.puts(Time.now.ctime)
  client.puts "Over & out!"
  client.close                
}

TCP Client

require 'socket'
s = TCPSocket.open('127.0.0.1', 23456)
while line = s.gets 
  puts line.chop   
end
s.close    


Parsing HTML

The text points out that regular expressions can be used
to parse HTML, but it is not as easy a task as one might
one to deal with. Following is an example of a regular
expression based parse.

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

require 'open-uri'
page = open('http://pragprog.com/titles/ruby3/programming-ruby-1-9').read
if page =~ %r{<title>(.*?)</title>}m
puts "Title is #{$1.inspect}"
end

OUTPUT

Title is "The Pragmatic Bookshelf | Programming Ruby 1.9"


The Hpricot Library

Ruby developers supply a superior package that is very popular
called the Hpricot library that is especially designed to parse HTML.


The following example from the text shows how it is used. You
will need
to go through some extra installs in order to try the
library out.

Example // from Programming Ruby, 1.9.2, Thomas,Fowler & Hunt

require 'open-uri'
require 'hpricot'
page = Hpricot(open('http://pragprog.com'))
puts "Page title is " + page.at(:title).inner_html
# Output the first paragraph in the div with an id="copyright"
puts page.at('div#copyright p')
# Output the second hyperlink in the site-links div
puts "\nSecond hyperlink is"
puts page.at('div#site-links a:nth(2)')


Assignment



Q.1 Use subclassing to create an exception that is fired
when a catastrophe is imminent at a nuclear
power plant.
Throw the exception using the raise
command and capture
it in a begin block's rescue
clause. ( An example is provided
below. )

Q.2 Create an exception class that extends RuntimeError
and is designed to carry a message. Raise the exception
in a begin block so that in the rescue block the message
is put to console.  (Refer to the example used in Q. 1)

Q.3  Use the example below or do from a clean sheet a
nested catch throw where on a condition that is reached
the outer catch is labelled so it is terminated.

Q.4 For the record, use the classic while loop to put some
verse stored in a File to console. Then use a writing method
to add a comment to the file. Then again, use a while loop
to show the file contents with the comment appended. 


Q.5 Using the examples below, where the UDP example sends
something to the server and the TCP examples sends something
back to the client, create a client server program that on sending
your name, the server sends back a day account number for a
convention.

The servers sends something like "Hello  Harry Smith! Your day
account number is 1234567."  ( Make it a bit  real by using an
increment operation  to ensure different account numbers are
given to each person.) 


Question Examples   // examples are from text above




Q.1 & 2 Example

class LogicalException < StandardError
attr :message
def initialize(message)
@message = message
end
end

begin if (true) raise LogicalException.new("The \'I always lie\' Paradox") end rescue LogicalException=> er puts er.message end
OUTPUT
The 'I always lie' Paradox




Q.3 Examples


The catch .. throw Form

catch ( :label, 2nd_arg_return_ val ) {
throw :label
}

Example

File.open("milton.txt",
"a") do |file|

file.puts
"\n\n Comments \n\n"

file.puts
"Really enjoyed the blurb on Milton - Tony Mills"


end


Example

catch (:done) do
x=0
2.times{x+=1; puts "Doing Stuff"}
puts x
if (x>=2) # increase 'trip value' to 3 and throw won't execute
throw :done
end
2.times{puts "Doing More Stuff But ..."}
end



Q.4 Example

file
= File.new("Milton.txt", "r+")
while line =
file.gets
puts line
end
file.close


Q.5 Examples
TCP Server Example

//
adapted from example at Tutorial Points, see references for URL


require 'socket'             
server =TCPServer.open(23456)
loop{                      
client =server.accept    
client.puts(Time.now.ctime)
client.puts "Over & out!"
client.close                
}


TCP
Client


require 'socket'
s =TCPSocket.open('127.0.0.1', 23456)
while line = s.gets 
puts line.chop   
end
s.close    
 
Example
//
from LeeJava Wordpress,

http://leejava.wordpress.com/2009/08/24/udp-client-and-server-in-ruby/


UDP Server
Example


require 'socket'
s= UDPSocket.news.
bind(nil,1234)

5.times do
text, sender = s.recvfrom(16)
puts text
end



UDP Client
Example


require
'socket'

s =
UDPSocket.new

s.send("hello",
0, 'localhost', 1234)