Hi, I''m playing with a scenario where I have a single server and multiple clients. The server maintains the client addresses and tells new clients about the others. Then typically a new client contacts the other clients to start exchanging some data. So it goes like: 1. Client request client list from server 2. Server returns client list 3. Client gets client list 4. Client contacts other clients I''m having difficulties with the fourth step: the messages to other clients never get sent. What I''m doing is, within the same interaction as the receiving from the server (step 3), I directly invoke all other clients: # Client receive * def receive_data(data) # Got peers addresses from server if data =~ /^SWARM-GET-RESPONSE/ peers = data.chomp.split("\n")[1] if peers @peers.concat(peers.split("|").map { |s| s.split(":") }) EM.defer(proc { @peers.each { |host, port| send_datagram("PEER~GET\n", host, port) } } ) end end ... *I''ve checked all sort of variations around the same pattern but didn''t get anything working unless the call is made from post_init instead of receive_data. My understanding is that it should be possible to send a datagram to a node while receiving from another node but I''m now wondering if my understanding is correct. If not, how can I do this? Thanks! Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071109/979f901f/attachment.html
On Nov 10, 2007 5:47 AM, garbagecat10 at gmail.com <garbagecat10 at gmail.com> wrote:> > Why are you using EM#defer? I don''t think you need it. > >I was using it to avoid holding too much on the receive as sending to many other clients could potentially take a lot of time. But I tried to remove it to see if it made any difference and still had the exact same problem. I even tried to differ the sending with a timer and still no difference. Thanks, Matthieu> _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/eventmachine-talk >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071110/f2326d77/attachment.html
On 11/10/07, Matthieu Riou <matthieu at offthelip.org> wrote:> > Hi, > > I''m playing with a scenario where I have a single server and multiple > clients. The server maintains the client addresses and tells new clients > about the others. Then typically a new client contacts the other clients to > start exchanging some data. So it goes like: > > 1. Client request client list from server > 2. Server returns client list > 3. Client gets client list > 4. Client contacts other clients > > I''m having difficulties with the fourth step: the messages to other > clients never get sent. What I''m doing is, within the same interaction as > the receiving from the server (step 3), I directly invoke all other clients: > > > # Client receive > * def receive_data(data) > # Got peers addresses from server > if data =~ /^SWARM-GET-RESPONSE/ > peers = data.chomp.split("\n")[1] > if peers > @ peers.concat(peers.split("|").map { |s| s.split(":") }) > EM.defer(proc { @peers.each { |host, port| > send_datagram("PEER~GET\n", host, port) } } ) > end > end > ... > > *I''ve checked all sort of variations around the same pattern but didn''t > get anything working unless the call is made from post_init instead of > receive_data. My understanding is that it should be possible to send a > datagram to a node while receiving from another node but I''m now wondering > if my understanding is correct. If not, how can I do this?Your code should work. I just wrote a program that does more or less what you describe and it''s fine. EM::Connection#send_datagram can be used within #receive_data. Are you sure that you''re parsing the hostname and ports correctly from your data? Don''t worry about defer and timers for sending UDP packets, just send them all in one go. If you have to send tens of thousands of them at once, then your kernel might drop some, but that''s normal for UDP. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071110/a1b799dd/attachment.html
On Nov 10, 2007 12:22 PM, Francis Cianfrocca <garbagecat10 at gmail.com> wrote:> On 11/10/07, Matthieu Riou <matthieu at offthelip.org> wrote: > > > Hi, > > > > I''m playing with a scenario where I have a single server and multiple > > clients. The server maintains the client addresses and tells new clients > > about the others. Then typically a new client contacts the other clients to > > start exchanging some data. So it goes like: > > > > 1. Client request client list from server > > 2. Server returns client list > > 3. Client gets client list > > 4. Client contacts other clients > > > > I''m having difficulties with the fourth step: the messages to other > > clients never get sent. What I''m doing is, within the same interaction as > > the receiving from the server (step 3), I directly invoke all other clients: > > > > > > # Client receive > > * def receive_data(data) > > # Got peers addresses from server > > if data =~ /^SWARM-GET-RESPONSE/ > > peers = data.chomp.split("\n")[1] > > if peers > > @ peers.concat(peers.split("|").map { |s| s.split(":") }) > > EM.defer(proc { @peers.each { |host, port| > > send_datagram("PEER~GET\n", host, port) } } ) > > end > > end > > ... > > > > *I''ve checked all sort of variations around the same pattern but didn''t > > get anything working unless the call is made from post_init instead of > > receive_data. My understanding is that it should be possible to send a > > datagram to a node while receiving from another node but I''m now wondering > > if my understanding is correct. If not, how can I do this? > > > > Your code should work. I just wrote a program that does more or less what > you describe and it''s fine. EM::Connection#send_datagram can be used within > #receive_data. >Could you post your code so I can check what differs from mine? You''re sending a datagram to a different address/port than the one who originated the received message right? And thanks a lot for trying this out!> > Are you sure that you''re parsing the hostname and ports correctly from > your data? >Unfortunately yes. I''ve checked a gazillion times that the host and port extracted where correct.> > Don''t worry about defer and timers for sending UDP packets, just send them > all in one go. If you have to send tens of thousands of them at once, then > your kernel might drop some, but that''s normal for UDP. >Thanks for the tip! Matthieu> > > _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/eventmachine-talk >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071110/b02ee273/attachment-0001.html
Forget what I said, I found the problem. It took me quite a bit of time to find it though, as always for those kind of frustrating bugs, it was dead simple. The port value I was giving to send_datagram, was a string containing a number and not a number... somehow this caused the whole thing to be ignored. I''d suggest the following patch on lib/eventmachine.rb: 1279c1279 < EventMachine::send_datagram @signature, data, data.length, recipient_address, recipient_port ---> EventMachine::send_datagram @signature, data, data.length,recipient_address, Integer(recipient_port) The Integer kernel method will throw an exception if the port can''t be converted to a number, whereas to_i would just try to find as many numbers as possible from the provided string, dropping the rest (which could also cause some other unintended bugs). Thanks for your help! Matthieu On Nov 10, 2007 12:54 PM, Matthieu Riou <matthieu at offthelip.org> wrote:> On Nov 10, 2007 12:22 PM, Francis Cianfrocca <garbagecat10 at gmail.com> > wrote: > > > On 11/10/07, Matthieu Riou <matthieu at offthelip.org> wrote: > > > > > Hi, > > > > > > I''m playing with a scenario where I have a single server and multiple > > > clients. The server maintains the client addresses and tells new clients > > > about the others. Then typically a new client contacts the other clients to > > > start exchanging some data. So it goes like: > > > > > > 1. Client request client list from server > > > 2. Server returns client list > > > 3. Client gets client list > > > 4. Client contacts other clients > > > > > > I''m having difficulties with the fourth step: the messages to other > > > clients never get sent. What I''m doing is, within the same interaction as > > > the receiving from the server (step 3), I directly invoke all other clients: > > > > > > > > > # Client receive > > > * def receive_data(data) > > > # Got peers addresses from server > > > if data =~ /^SWARM-GET-RESPONSE/ > > > peers = data.chomp.split("\n")[1] > > > if peers > > > @ peers.concat(peers.split("|").map { |s| s.split(":") }) > > > EM.defer(proc { @peers.each { |host, port| > > > send_datagram("PEER~GET\n", host, port) } } ) > > > end > > > end > > > ... > > > > > > *I''ve checked all sort of variations around the same pattern but > > > didn''t get anything working unless the call is made from post_init instead > > > of receive_data. My understanding is that it should be possible to send a > > > datagram to a node while receiving from another node but I''m now wondering > > > if my understanding is correct. If not, how can I do this? > > > > > > > > Your code should work. I just wrote a program that does more or less > > what you describe and it''s fine. EM::Connection#send_datagram can be used > > within #receive_data. > > > > Could you post your code so I can check what differs from mine? You''re > sending a datagram to a different address/port than the one who originated > the received message right? And thanks a lot for trying this out! > > > > > > Are you sure that you''re parsing the hostname and ports correctly from > > your data? > > > > Unfortunately yes. I''ve checked a gazillion times that the host and port > extracted where correct. > > > > > > Don''t worry about defer and timers for sending UDP packets, just send > > them all in one go. If you have to send tens of thousands of them at once, > > then your kernel might drop some, but that''s normal for UDP. > > > > Thanks for the tip! > > Matthieu > > > > > > > > _______________________________________________ > > Eventmachine-talk mailing list > > Eventmachine-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/eventmachine-talk > > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071110/5ee9d233/attachment.html
On 11/10/07, Matthieu Riou <matthieu at offthelip.org> wrote:> > On Nov 10, 2007 12:22 PM, Francis Cianfrocca <garbagecat10 at gmail.com> > wrote: > > > On 11/10/07, Matthieu Riou <matthieu at offthelip.org> wrote: > > > > > Hi, > > > > > > I''m playing with a scenario where I have a single server and multiple > > > clients. The server maintains the client addresses and tells new clients > > > about the others. Then typically a new client contacts the other clients to > > > start exchanging some data. So it goes like: > > > > > > 1. Client request client list from server > > > 2. Server returns client list > > > 3. Client gets client list > > > 4. Client contacts other clients > > > > > > I''m having difficulties with the fourth step: the messages to other > > > clients never get sent. What I''m doing is, within the same interaction as > > > the receiving from the server (step 3), I directly invoke all other clients: > > > > > > > > > # Client receive > > > * def receive_data(data) > > > # Got peers addresses from server > > > if data =~ /^SWARM-GET-RESPONSE/ > > > peers = data.chomp.split("\n")[1] > > > if peers > > > @ peers.concat(peers.split("|").map { |s| s.split(":") }) > > > EM.defer(proc { @peers.each { |host, port| > > > send_datagram("PEER~GET\n", host, port) } } ) > > > end > > > end > > > ... > > > > > > *I''ve checked all sort of variations around the same pattern but > > > didn''t get anything working unless the call is made from post_init instead > > > of receive_data. My understanding is that it should be possible to send a > > > datagram to a node while receiving from another node but I''m now wondering > > > if my understanding is correct. If not, how can I do this? > > > > > > > > Your code should work. I just wrote a program that does more or less > > what you describe and it''s fine. EM::Connection#send_datagram can be used > > within #receive_data. > > > > Could you post your code so I can check what differs from mine? You''re > sending a datagram to a different address/port than the one who originated > the received message right? And thanks a lot for trying this out! >Three programs. The first one receives and prints a datagram: require ''rubygems'' require ''eventmachine'' module A def receive_data a p a end end EM.run { p "Listening on 9600" EM.open_datagram_socket "192.168.0.8", 9600, A } -------------------------------------------------------------------------------------- The second one waits to receive a datagram, then sends it to a different port. require ''rubygems'' require ''eventmachine'' module A def receive_data a p a send_datagram "<#{a}>", "192.168.0.8", 9600 end end EM.run { p "Listening on 9601, sending to 9600" EM.open_datagram_socket "192.168.0.8", 9601, A } ----------------------------------------------------------------- The third one sends a datagram to start off the process: require ''rubygems'' require ''eventmachine'' module G def post_init send_datagram "AAA", "192.168.0.8", 9601 end end EM.run { EM.open_datagram_socket "192.168.0.8", 0, G } -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071110/3d63417c/attachment.html
On 11/10/07, Matthieu Riou <matthieu at offthelip.org> wrote:> > Forget what I said, I found the problem. It took me quite a bit of time to > find it though, as always for those kind of frustrating bugs, it was dead > simple. The port value I was giving to send_datagram, was a string > containing a number and not a number... somehow this caused the whole thing > to be ignored. > > I''d suggest the following patch on lib/eventmachine.rb: > > 1279c1279 > < EventMachine::send_datagram @signature, data, data.length, > recipient_address, recipient_port > --- > > EventMachine::send_datagram @signature, data, data.length, > recipient_address, Integer(recipient_port) > > The Integer kernel method will throw an exception if the port can''t be > converted to a number, whereas to_i would just try to find as many numbers > as possible from the provided string, dropping the rest (which could also > cause some other unintended bugs).Thanks for the suggestion. Accepted and checked into HEAD revision. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071110/ca65630b/attachment.html
On Nov 10, 1:33 am, "Matthieu Riou" <matth... at offthelip.org> wrote:> Hi, > > I''m playing with a scenario where I have a single server and multiple > clients. The server maintains the client addresses and tells new clients > about the others. Then typically a new client contacts the other clients to > start exchanging some data. So it goes like: > > 1. Client request client list from server > 2. Server returns client list > 3. Client gets client list > 4. Client contacts other clients > > I''m having difficulties with the fourth step: the messages to other clients > never get sent. What I''m doing is, within the same interaction as the > receiving from the server (step 3), I directly invoke all other clients: > > # Client receive > * def receive_data(data) > # Got peers addresses from server > if data =~ /^SWARM-GET-RESPONSE/ > peers = data.chomp.split("\n")[1] > if peers > @peers.concat(peers.split("|").map { |s| s.split(":") }) > EM.defer(proc { @peers.each { |host, port| > send_datagram("PEER~GET\n", host, port) } } ) > end > end > ... >Why are you using EM#defer? I don''t think you need it.