celluloid-io: Socket-Server and client at the same time

226 views
Skip to first unread message

peter.j....@googlemail.com

unread,
Mar 7, 2013, 10:22:36 AM3/7/13
to cellulo...@googlegroups.com
I did some tests with the celluloid-io examples and I am wondering whether it is possible to run a Socket-Server and Socket Client at the same time with celluloid.

Usually we would use 2 separate processes but in my case I want to receive requests on port 8000 from a couple of clients and want to answer them asynchroneously from the same port 8000 (requiremenet from the counterpart application). This requires that both, the receiving part and the sending parts shall work on port 8000.

The echo application and the receiving part is trivial for me, but I would need a basic example where I may receive data from another source through ZMQ or IRB, then identify which client I have to connect to (I think somehow via registry) and then send the data.

Any help is welcome.


peter.j....@googlemail.com

unread,
Mar 7, 2013, 4:01:09 PM3/7/13
to cellulo...@googlegroups.com
Finally I figured it out myself
class Server1
  include Celluloid::IO
end
class Server2
  include Celluloid::IO
end
supervisor_a = Server1.supervise("127.0.0.1", 8000)
supervisor_b = Server1.supervise("127.0.0.1", 8001)
sleep

In Server1 I store all connections sockets objects in a hash $connections
When I receive events on Server2 I lookup $connections for the right socket and send the data through this socket object.

It was easier than expected. very nice tool!

Best regards
Peter

Charles Remes

unread,
Mar 7, 2013, 4:02:23 PM3/7/13
to cellulo...@googlegroups.com
Any chance you could contribute a working example back for the examples/ directory? It would be great to have a non-trivial example for using celluloid-io.


--
You received this message because you are subscribed to the Google Groups "Celluloid" group.
To unsubscribe from this group and stop receiving emails from it, send an email to celluloid-rub...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

peter.j....@googlemail.com

unread,
Mar 11, 2013, 5:21:07 AM3/11/13
to cellulo...@googlegroups.com
Here you find an example

#!/usr/bin/env ruby

require 'celluloid/io'

# This class simply receives commands from an Appserver, echos them back and distributes the commands to all connected clients
class AppServer
  include Celluloid::IO

  def initialize(host, port)
    puts "AppServer *** Starting server on #{host}:#{port}"
    @server = TCPServer.new(host, port)
    async.run
    $sockets_appserver={}
  end

  def finalize
    @server.close if @server
  end

  def run
    loop { async.handle_connection @server.accept }
  end

  def handle_connection(socket)
    _, port, host = socket.peeraddr
    puts "AppServer *** Received connection from #{host}:#{port}"
    loop {
      received=socket.readpartial(4096)
      socket.write received
      send_data_all(received)
    }
  rescue EOFError
    puts "AppServer *** #{host}:#{port} disconnected"
    socket.close
  end

  # all established client sockets are stored in $sockets_clients
  def send_data_all(data)
    puts "Size: #{$sockets_clients.size}"
    $sockets_clients.each do |port,socket|
      puts "Sending data to port #{port}"
      socket.write data
    end
  end

end # class

# Class where cxlients can connect
class ClientsServer
  include Celluloid::IO

  def initialize(host, port)
    puts "*** Starting echo server on #{host}:#{port}"
    # Since we included Celluloid::IO, we're actually making a
    # Celluloid::IO::TCPServer here
    @server = TCPServer.new(host, port)
    async.run
    $sockets_clients={}
  end

  def finalize
    @server.close if @server
  end

  def run
    loop { async.handle_connection @server.accept }
  end

  def get_sockets
    puts "ClientsServer Sockets Size: #{$sockets_clients.size}"
  end

  # register all connected clients and store them into $sockets_clients
  # for simple testing we only store port, not the corresponding ips yet, as we only test locally.
  def register(port,socket)
    if !$sockets_clients[port]
      $sockets_clients[port]=socket
      puts "clients clients size: #{$sockets_clients.size}"
    end
  end

  def unregister(port)
    if $sockets_clients[port]
      $sockets_clients.delete(port)
      puts "clients clients size: #{$sockets_clients.size}"
    end
  end

  def handle_connection(socket)
    _, port, host = socket.peeraddr
    puts "ClientsServer *** Received connection from #{host}:#{port}"
    register(port,socket)
    loop {
      received=socket.readpartial(4096)
      socket.write received
      get_sockets
    }
  rescue EOFError
    unregister(port)
    puts "ClientsServer *** #{host}:#{port} disconnected"
    socket.close

  end
end

supervisor_f = ClientsServer.supervise("127.0.0.1", 1234)
supervisor_a = AppServer.supervise("127.0.0.1", 1235)
trap("INT") { supervisor_f.terminate; supervisor_a.terminate; exit }
sleep

Jérémy Van de Wyngaert

unread,
Mar 11, 2013, 6:46:17 PM3/11/13
to cellulo...@googlegroups.com
You can get rid of $sockets_appserver

Don't you should use a Mutex when mutating $sockets_clients of use some kind of thread safe data structure like Hamster?

Руслан Корнев

unread,
May 7, 2017, 9:52:52 PM5/7/17
to Celluloid
agree with Jérémy Van de Wyngaert comment
is it safe to write to socket from other thread?

вторник, 12 марта 2013 г., 1:46:17 UTC+3 пользователь Jérémy Van de Wyngaert написал:
Reply all
Reply to author
Forward
0 new messages