Mark Van De Vyver
2007-May-08 16:16 UTC
[Eventmachine-talk] send_data using multiple connections from
Hi, To understand EM a little better I''ve merged a couple of examples. One from Francis (the conn_list) and the other from Eloy Duran (the threading idea) I''m interested in being able to create several connections, and sending/receiving data on them. I''d also appreciate any tips on a better way to achieve the same effect. If I comment out the Thread related code (including the very last command) things seem to run, in that I see: *... Now accepting connections on address 192.168.1.1, port 8090... Received a new connection connection completed... Echo [#<Echo:0xb792888c @signature="1ba0acb0aa0debe146bf4a2f566ef6183">] *... [#<Echo:0xb792888c @signature="1ba0acb0aa0debe146bf4a2f566ef6183">] Hoverver, if I run the code as it is below, I see: Now accepting connections on address 192.168.1.1, port 8090... The client is sending: We should see this text... The problem seems to be related to the use of threads. There are no exceptions thrown, and it seems that client and server instances are not created. I appreciate if anyone can point out where I have gone wrong. Thanks in advance Mark # Example code below require ''rubygems'' require ''eventmachine'' module EchoServer def post_init puts "Received a new connection" @data_received = "" @line_count = 0 end def receive_data data send_data ">> #{data}" puts "The server received: #{data} \nThen sent: >> #{data}" close_connection if data =~ /quit/i end end class Echo < EventMachine::Connection @@conn_list = [] def self.print_connections p @@conn_list end def initialize *args super @@conn_list << self end def post_init # your normal processing end def connection_completed puts "connection completed... #{self.class.name}" end def receive_data data # your normal processing puts "The client received: #{data}" puts self.print_connections end def client_send_data data puts "The client is sending: #{data}" send_data data end def unbind @@conn_list.delete self end end begin @my_conn_threads = Thread.new do t = Thread.current host,port = "192.168.1.1", 8090 EventMachine::run { t[:server] = EventMachine::start_server host, port, EchoServer puts "Now accepting connections on address #{host}, port #{port}..." t[:client] = EventMachine::connect host, port, Echo EventMachine::add_periodic_timer( 2 ) { $stderr.write "*...\n" Echo.print_connections } } end rescue => err puts err end @my_conn_threads[:client].client_send_data "We should see this text... \n"
Mark Van De Vyver
2007-May-09 16:50 UTC
[Eventmachine-talk] send_data using multiple connections from
Hi, I have managed to get this example working,,, ! I''m going to top post since this replaces my earlier email. There was one gotcha that I really don''t understand the reason for: In the Echo#receive_data( data ) method, the line: puts self.print_connections should be puts Echo.print_connections If you examine the output carefully you''ll notice a ''nil'' is printed to the screen after the connections list is printed..... I have no idea where that is coming from, and it quite possibly is a symptom of a serious or trivial problem - use at your own risk :) Apart from that the code of Francis and Eloy is pretty much as is. I hope this helps someone else understand/appreciate how great the work of the EventMachine developers is! Thanks again Mark #!/usr/bin/ruby require ''thread'' require ''rubygems'' require ''eventmachine'' module EchoServer def post_init puts "Received a new connection" @data_received = "" @line_count = 0 end def receive_data data send_data ">> #{data}" puts "The server received: #{data} \nThen the server sent: >> #{data}" close_connection if data =~ /quit/i end end class Echo < EventMachine::Connection @@conn_list = [] def self.print_connections p @@conn_list end def initialize *args super @@conn_list << self end def post_init # your normal processing end def connection_completed puts "connection completed... #{self.class.name}" end def receive_data data # your normal processing puts "The client received: #{data}" puts Echo.print_connections end def client_send_data data puts "The client is sending: #{data}" send_data data end def unbind @@conn_list.delete self end end host,port = "192.168.1.1", 8090 Thread.abort_on_exception = true begin @my_em_run_thread = Thread.new do EventMachine::run { Thread.current[:server] = EventMachine::start_server host, port, EchoServer puts "Now accepting connections on address #{host}, port #{port}..." Thread.current[:client_1] = EventMachine::connect host, port, Echo Thread.current[:client_2] = EventMachine::connect host, port, Echo Thread.current[:client_3] = EventMachine::connect host, port, Echo Thread.current[:client_4] = EventMachine::connect host, port, Echo EventMachine::add_periodic_timer( 10 ) { $stderr.write "*...\n" Echo.print_connections } } # EventMachine::run end # Thread.new rescue => err puts err end # begin # # Using one connection # puts @my_em_run_thread.status @my_em_run_thread[:client_1].client_send_data "On client_1 connection, we should see this text... first \n" @my_em_run_thread[:client_1].client_send_data "On client_1 connection, we should see this text... second \n" sleep(1) @my_em_run_thread[:client_1].client_send_data "On client_1 connection, we should see this text... third \n" sleep(1) @my_em_run_thread[:client_1].client_send_data "On client_1 connection, we should see this text... last! \n" # # Using all connections # @my_em_run_thread[:client_4].client_send_data "On client_4 connection, we _should_ see this text... out of order \n" @my_em_run_thread[:client_3].client_send_data "On client_3 connection, we _should_ see this text... out of order \n" sleep(1) @my_em_run_thread[:client_2].client_send_data "On client_2 connection, we should see this text... third \n" sleep(1) @my_em_run_thread[:client_1].client_send_data "On client_1 connection, we should see this text... last! \n" puts @my_em_run_thread.status @my_em_run_thread.join # Force a wait here indefinitely On 5/9/07, Mark Van De Vyver <mvyver at gmail.com> wrote:> Hi, > To understand EM a little better I''ve merged a couple of examples. One > from Francis (the conn_list) and the other from Eloy Duran (the > threading idea) > I''m interested in being able to create several connections, and > sending/receiving data on them. I''d also appreciate any tips on a > better way to achieve the same effect. > > If I comment out the Thread related code (including the very last > command) things seem to run, in that I see: > > *... > Now accepting connections on address 192.168.1.1, port 8090... > Received a new connection > connection completed... Echo > [#<Echo:0xb792888c @signature="1ba0acb0aa0debe146bf4a2f566ef6183">] > *... > [#<Echo:0xb792888c @signature="1ba0acb0aa0debe146bf4a2f566ef6183">] > > Hoverver, if I run the code as it is below, I see: > > Now accepting connections on address 192.168.1.1, port 8090... > The client is sending: We should see this text... > > > The problem seems to be related to the use of threads. There are no > exceptions thrown, and it seems that client and server instances are > not created. > > I appreciate if anyone can point out where I have gone wrong. > > Thanks in advance > Mark > > # Example code below > > require ''rubygems'' > require ''eventmachine'' > > module EchoServer > def post_init > puts "Received a new connection" > @data_received = "" > @line_count = 0 > end > > def receive_data data > send_data ">> #{data}" > puts "The server received: #{data} \nThen sent: >> #{data}" > close_connection if data =~ /quit/i > end > end > > class Echo < EventMachine::Connection > > @@conn_list = [] > > def self.print_connections > p @@conn_list > end > > def initialize *args > super > @@conn_list << self > > end > > def post_init > # your normal processing > end > def connection_completed > puts "connection completed... #{self.class.name}" > end > def receive_data data > # your normal processing > puts "The client received: #{data}" > puts self.print_connections > end > > def client_send_data data > puts "The client is sending: #{data}" > send_data data > end > def unbind > @@conn_list.delete self > end > > end > > begin > @my_conn_threads = Thread.new do > t = Thread.current > host,port = "192.168.1.1", 8090 > EventMachine::run { > t[:server] = EventMachine::start_server host, port, EchoServer > puts "Now accepting connections on address #{host}, port #{port}..." > t[:client] = EventMachine::connect host, port, Echo > EventMachine::add_periodic_timer( 2 ) { > $stderr.write "*...\n" > Echo.print_connections > } > } > end > rescue => err > > puts err > > end > > @my_conn_threads[:client].client_send_data "We should see this text... \n" >