Twisted

Twisted is an event-driven networking engine written in Python and licensed under the open source MIT license.

Install from source

Test installation

Slackbuild

Slackware64 14: python-twisted-13.2.0-x86_64-1_SBo.tgz

Echo server

   1 from twisted.internet import protocol, reactor
   2 
   3 class Echo(protocol.Protocol):
   4     def dataReceived(self, data):
   5         self.transport.write(data)
   6 
   7     def connectionMade(self):
   8         print('Connection made')
   9 
  10     def connectionLost(self,reason):
  11         print('Connection lost')
  12 class EchoFactory(protocol.Factory):
  13     def buildProtocol(self, addr):
  14         return Echo()
  15 
  16 if __name__=='__main__':
  17     reactor.listenTCP(1234, EchoFactory())
  18     reactor.run()

Echo client

   1 import threading
   2 import time
   3 import socket
   4 
   5 class Client (threading.Thread):
   6     def __init__(self):
   7         threading.Thread.__init__(self) #required
   8                 
   9     def run(self):
  10         for x in range(1,100):
  11             HOST = 'localhost'
  12             PORT = 1234
  13             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  14             print('connecting...')
  15             s.connect((HOST, PORT))
  16             print('sending config...')
  17             s.send('test')
  18             s.close()
  19             print('complete')
  20 
  21 if __name__=='__main__':
  22 
  23     clients=[]
  24     for x in range(1,100):
  25         clients.append( Client() )
  26 
  27     for c in clients:
  28         c.start()

Sample web server

   1 # from https://twistedmatrix.com/trac/
   2 from twisted.web import server, resource
   3 from twisted.internet import reactor, endpoints
   4 
   5 class Counter(resource.Resource):
   6     isLeaf = True
   7     numberRequests = 0
   8 
   9     def render_GET(self, request):
  10         self.numberRequests += 1
  11         request.setHeader(b"content-type", b"text/plain")
  12         content = u"I am request #{}\n".format(self.numberRequests)
  13         return content.encode("ascii")
  14 
  15 endpoints.serverFromString(reactor, "tcp:8080").listen(server.Site(Counter()))
  16 reactor.run()

/etc/nginx/conf.d/load-balancer.conf

upstream backend {
   server 172.28.128.4:8080;
   server 172.28.128.3:8080;
   server 172.28.128.6:8080;
}

server {
   listen 8080;

   location / {
      proxy_pass http://backend;
   }
}

twistedtest.py

   1 from twisted.web import server
   2 from twisted.web import resource
   3 from twisted.internet import reactor
   4 from twisted.internet import endpoints
   5 import time
   6 import sys
   7 
   8 class Handler(resource.Resource):
   9     isLeaf = True
  10     numberRequests = 0
  11 
  12     def render_GET(self, request):
  13         self.numberRequests += 1
  14         time.sleep(0.1) # wait 100 ms
  15         request.setHeader(b"content-type", b"text/plain")
  16         content = u"I am request #{}\n".format(self.numberRequests)
  17         return content.encode("ascii")
  18 
  19 if __name__=='__main__':
  20     port = sys.argv[1]
  21     print('Listening on port %s'%(port))
  22     endpoints.serverFromString(reactor,"tcp:%s" %(port) ).listen(server.Site(Handler()))
  23     reactor.run()

twistedclient.py

   1 import threading
   2 import urllib2
   3 import time
   4 import sys
   5 
   6 class Client(threading.Thread):
   7     def __init__(self,urls,nrReqs):
   8         threading.Thread.__init__(self) #required
   9         self.urls=urls
  10         self.nrReqs=nrReqs
  11         self.count=0       
  12     def run(self):
  13         loop=True
  14         urlIdx=0
  15         while loop:
  16             url=urls[urlIdx]
  17             conn=urllib2.urlopen(url)
  18             resp=conn.read()   
  19             if self.count < self.nrReqs-1:
  20                 self.count+=1
  21                 urlIdx+=1
  22                 if urlIdx>=len(urls):
  23                     urlIdx=0
  24             else:
  25                 loop=False
  26                 
  27 if __name__=='__main__':      
  28     if len(sys.argv) == 4:
  29         nrUrlsToUse = int(sys.argv[1])
  30         nrClients=int(sys.argv[2])
  31         nrReqs=int(sys.argv[3])
  32     
  33         start = time.time()
  34         urls=['http://localhost:8080/','http://localhost:8081/','http://localhost:8082/','http://localhost:8083/','http://localhost:8084/','http://localhost:8085/','http://localhost:8086/','http://localhost:8087/','http://localhost:8088/','http://localhost:8089/','http://localhost:8090/','http://localhost:8091/','http://localhost:8092/','http://localhost:8093/','http://localhost:8094/','http://localhost:8095/','http://localhost:8096/','http://localhost:8097/','http://localhost:8098/','http://localhost:8099/']
  35     
  36         if nrUrlsToUse<len(urls):
  37             urls = urls[0:nrUrlsToUse]
  38     
  39 
  40         clients=[]
  41     
  42         for client in range(0,nrClients):
  43             c = Client(urls,nrReqs)
  44             clients.append( c )
  45             c.start()
  46         
  47         for client in clients:
  48             client.join()
  49         
  50         end = time.time()
  51         delta = end-start
  52         totalRequests = nrReqs*nrClients
  53         reqPerSec = totalRequests/delta
  54         print('Test time: %d Total requests:%d ReqsPerSec:%f TotalURLs: %d'%(delta,totalRequests,reqPerSec,len(urls)))
  55     else:
  56         print('Usage: twistedclient.py <nrUrlsToUse> <nrClients> <nrReqs>')    

Python/Twisted (last edited 2020-01-03 17:01:46 by localhost)