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"
>