title: Twisted / Amp networking: Respond to all clients, not just one making a request
body: <p>I'm trying to learn my way around these newfangled "factory" style network libraries. Twisted comes with much acclaim, but is an absolute nightmare for me, since I am not familiar with lambda and thus I'm really not sure how to follow what the demo code is doing.</p>
  
  <p>demo client:</p>
  
  <pre><code>from twisted.internet import reactor, defer
  from twisted.internet.protocol import ClientCreator
  from twisted.protocols import amp
  from ampserver import Sum, Divide
  
  
  def doMath():
      d1 = ClientCreator(reactor, amp.AMP).connectTCP(
          '127.0.0.1', 1234).addCallback(
              lambda p: p.callRemote(Sum, a=13, b=81)).addCallback(
                  lambda result: result['total'])
      def trapZero(result):
          result.trap(ZeroDivisionError)
          print "Divided by zero: returning INF"
          return 1e1000
      d2 = ClientCreator(reactor, amp.AMP).connectTCP(
          '127.0.0.1', 1234).addCallback(
              lambda p: p.callRemote(Divide, numerator=1234,
                                     denominator=0)).addErrback(trapZero)
      def done(result):
          print 'Done with math:', result
      defer.DeferredList([d1, d2]).addCallback(done)
  
  if __name__ == '__main__':
      doMath()
      reactor.run()
  </code></pre>
  
  <p>Demo Server:</p>
  
  <pre><code>from twisted.protocols import amp
  
  class Sum(amp.Command):
      arguments = [('a', amp.Integer()),
                   ('b', amp.Integer())]
      response = [('total', amp.Integer())]
  
  
  class Divide(amp.Command):
      arguments = [('numerator', amp.Integer()),
                   ('denominator', amp.Integer())]
      response = [('result', amp.Float())]
      errors = {ZeroDivisionError: 'ZERO_DIVISION'}
  
  
  class Math(amp.AMP):
      def sum(self, a, b):
          total = a + b
          print 'Did a sum: %d + %d = %d' % (a, b, total)
          return {'total': total}
      Sum.responder(sum)
  
      def divide(self, numerator, denominator):
          result = float(numerator) / denominator
          print 'Divided: %d / %d = %f' % (numerator, denominator, result)
          return {'result': result}
      Divide.responder(divide)
  
  
  def main():
      from twisted.internet import reactor
      from twisted.internet.protocol import Factory
      pf = Factory()
      pf.protocol = Math
      reactor.listenTCP(1234, pf)
      print 'started'
      reactor.run()
  
  if __name__ == '__main__':
      main()
  </code></pre>
  
  <p>As I understand it, The client <code>p.callRemote(Sum, a=13, b=81)</code> and <code>p.callRemote(Divide, numerator=1234, denominator=0)</code> portions call <code>Math.sum(13, 81)</code> and <code>Math.Divide(1234, 0)</code>, because the factory object's <code>protocol</code> is set to the <code>Math</code> class. Somehow when the client receives the return value from the Server, the sub-function <code>Done(result)</code> is called, which prints stuff to the screen.</p>
  
  <p>This is great, but my comprehension sucks and every piece of documentation seems to expect this level of understanding already.</p>
  
  <p>What I really want to be able to do is send data from a client to a server, and from a server to several clients that are connected. This method seems to forget about a client as soon as the exchange is over, and <code>reactor.run()</code> blocks on the client, preventing it from doing any other work.</p>
  
  <p>People probably wish for this functionality every single day. How do I understand this?</p>
  
  <p>Edit: I've tried to have a "check in" function for the clients to call, but this seems like it would drown my server in requests just to respond "Nothing to report". Also, it adds delay, in that clients only receive new data when they ask for it, instead of when it actually becomes available. The factory - reactor layout doesn't seem to expose the client info I need to store in order to respond to them arbitrarily.</p>