Wednesday, August 17, 2011

Chat Application Using Ruby


Implementing a Chat application was never made so easy as it is now. Once done with the Chat application, I realized it was not that difficult to implement it in Ruby. It was just the need of using the right classes and methods with apt timing which gives one the end product Chat Application.

The below chat application is implemented using User Datagram Protocol( UDP ). Here we make use of the UDP Socket class in Ruby. UDP allows computers to send individual packets of data to other computers, without the overhead of establishing a persistent connection.

The Chat application given below is based on a Client Server model wherein the client sends a datagram containing a string of text to a specified host and port. The server, which is also running on the same host and listening on that port, receives the text and posts it on the terminal. Multiple clients can connect to the server and post their messages.

Every client is recognized with a unique client port number for every instance of it run on the terminal. Given below is the server script and the client script which have to be run one after the other. Here we have a 1:N relationship, thus for one server script run we can have multiple client scripts running alongside.

Here the server represents the chat room and the clients represents the users who are making use of the chat application for their purpose.

The server side script takes a command line argument which is basically the port number on which you are running the Chat application.

To run the server script, you need to enter the following command in the terminal:

ruby filename.rb 12345
Server side running script:
require 'socket'
#this is like the chat room..

port = ARGV[0]

ds = UDPSocket.new

ds.bind(nil,port)

$b = IO.new(2,"w+")

$client_id = 1
$clients = []
$flag = 0
loop do

    request, address = ds.recvfrom(1024)
    response = request
    clientaddr = address[3]
    clientname = address[2]
    clientport = address[1]

    if ( $clients.empty? )
        $clients[$client_id-1] = clientport
        puts "Client #{$client_id} enters the chat room "
        $client_id += 1
        puts "#{$clients}"
    else
        #puts(r.include? 'a')
        unless $clients.include? clientport       
            puts "Client #{$client_id} enters the chat room "
            $clients[$client_id-1] = clientport
            $client_id += 1
        end
        #    $client_id += 1
    end

#    puts "Connection from :Client #{clientport} says: #{response} #{clientname} #{clientaddr} #{clientport}"
    if( response.chop != "quit")
        puts "Client #{clientport}  says: #{response} "
    else
        puts "Client #{clientport} leaves the chat room "
        $client_id -= 1
    end

    if($client_id == 1)
        print " Do you want to close the chat room(y/n)?: "
            a = $b.readline
        if ( a.chop == "y")
            break
        end
    end
#    ds.send(response, 0, clientaddr, clientport)

end

Client side running script:
The client side script takes two command line arguments which are basically the host name and the port number on which you are running the Chat application.
To run the client script, you need to enter the following command in the terminal: ruby filename.rb hostname 12345
require 'socket'

host, port = ARGV

ds = UDPSocket.new
ds.connect(host,port)

request_message = ''
$a = IO.new(2,"w+")

while request_message.chop != "quit"
    puts "Enter Message: "
    request_message = $a.readline
#puts '{$client_id1} says:' + a
    ds.send(request_message,0)
#response,address = ds.recvfrom(1024)
#puts response
end
A client exits the chat application and leaves the chat room only on the entry of the string “quit”. When there are no clients, the server will prompt whether or not do you want to close the chat room. One chooses appropriately.

Output:
The output is basically a running chat application . Given below is a screen shot of the same with three clients running alongside one server.


2 comments:

  1. Hi,

    thanks for the post.
    I am getting an error while I am trying to configure your code.

    I am getting this error "client.rb:14:in `readline': Bad file descriptor (Errno::EBADF)"

    I am very much new to ruby world. Please help

    ReplyDelete
  2. Hi,

    The client.rb line 14 is commented in my code. I'm a little surprised how is that line of code giving you any error.

    Tell me how are you running both the ruby scripts ? I want to you tell me about the actual commands that you are using in your different terminal instances.

    Also, can you paste your code somewhere, it might help me better look into the problem your facing.

    ReplyDelete