使用Python的twisted和socket模块实现端口的负载分发
生活随笔
收集整理的這篇文章主要介紹了
使用Python的twisted和socket模块实现端口的负载分发
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
很簡單的需求,自己寫個類似iptables那樣的dnat端口轉發,簡單實現像lvs那樣的nat模式的端口的負載分發,當然性能堪憂哈~
這個例子是 監聽 本地ip的9999端口,然后映射到另一個端口上,也可以利用random參數,進行多個端口的輪訓,當然他的算法和性能簡單,不能和lvs 相比了。
映射的版本:
執行方法:python th.py 8888 10.10.10.63 80
#!/usr/bin/env python #python th.py 8888 10.10.10.63 80 import sys, socket, time, threading loglock = threading.Lock() def log(msg): loglock.acquire() try: print '[%s]: \n%s\n' % (time.ctime(), msg.strip()) sys.stdout.flush() finally: loglock.release() class PipeThread(threading.Thread): def __init__(self, source, target): threading.Thread.__init__(self) self.source = source self.target = target def run(self): while True: try: data = self.source.recv(1024) log(data) if not data: break self.target.send(data) except: break log('PipeThread done') class Forwarding(threading.Thread): def __init__(self, port, targethost, targetport): threading.Thread.__init__(self) self.targethost = targethost self.targetport = targetport self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.bind(('0.0.0.0', port)) self.sock.listen(10) def run(self): while True: client_fd, client_addr = self.sock.accept() target_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) target_fd.connect((self.targethost, self.targetport)) log('new connect') # two direct pipe PipeThread(target_fd, client_fd).start() PipeThread(client_fd, target_fd).start() if __name__ == '__main__': print 'Starting' import sys try: port = int(sys.argv[1]) targethost = sys.argv[2] try: targetport = int(sys.argv[3]) except IndexError: targetport = port except (ValueError, IndexError): print 'Usage: %s port targethost [targetport]' % sys.argv[0] sys.exit(1) #sys.stdout = open('forwaring.log', 'w') Forwarding(port, targethost, targetport).start()
附帶負載的版本:
#!/usr/bin/env python import sys, socket, time, threading loglock = threading.Lock() def log(msg): loglock.acquire() try: print '[%s]: \n%s\n' % (time.ctime(), msg.strip()) sys.stdout.flush() finally: loglock.release() class PipeThread(threading.Thread): def __init__(self, source, target): threading.Thread.__init__(self) self.source = source self.target = target def run(self): while True: try: data = self.source.recv(1024) log(data) if not data: break self.target.send(data) except: break log('PipeThread done') class Forwarding(threading.Thread): def __init__(self, port, targethost, targetport): number = random.randint(1,2) numbers = '%d' %number portlist={'1':80,'2':81} host='10.10.10.63' threading.Thread.__init__(self) self.targethost = targethost self.targetport = portlist[numbers] self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.bind(('0.0.0.0', port)) self.sock.listen(10) def run(self): while True: client_fd, client_addr = self.sock.accept() target_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) target_fd.connect((self.targethost, portlist[numbers])) log('new connect') # two direct pipe PipeThread(target_fd, client_fd).start() PipeThread(client_fd, target_fd).start() if __name__ == '__main__': print 'Starting' import sys import random number = random.randint(1,2) numbers = '%d' %number #sys.stdout = open('forwaring.log', 'w') portlist={'1':80,'2':81} host='10.10.10.63' Forwarding(9999,host, portlist[numbers]).start()
對于性能要求高的,可以試試twisted端口轉發的代碼。
調優方向 ?I/O模型,比如阻塞、非阻塞和反應式(select,poll,WaitForMultipleObject)
現在用gevent比較多,一是gevent性能會更好一些,而且用同步的方式來實現異步(使用greenlet),twisted中defer 和 callback 會把邏輯打散。 當初從twisted轉到gevent最主要的原因是在twisted上很難實現多進程。 gevent不好的地方就是它的mongkey_patch 有時候會帶來一些奇怪的問題。
個人感覺,twisted的優點是程序的各種設計,要是針對于咱們這個映射需求的話,推薦使用gevent網絡并發框架。 ?這個也是我較常用的。
from twisted.internet.protocol import Protocol,ClientCreator from twisted.internet import reactor from twisted.protocols.basic import LineReceiver from twisted.internet.protocol import Factory,ClientFactory class Transfer(Protocol): def __init__(self): pass def connectionMade(self): c = ClientCreator(reactor,Clienttransfer) c.connectTCP("10.10.10.63",80).addCallback(self.set_protocol) self.transport.pauseProducing() def set_protocol(self,p): self.server = p p.set_protocol(self) def dataReceived(self,data): self.server.transport.write(data) def connectionLost(self,reason): self.transport.loseConnection() self.server.transport.loseConnection() class Clienttransfer(Protocol): def __init__(self): pass def set_protocol(self,p): self.server = p self.server.transport.resumeProducing() pass def dataReceived(self,data): self.server.transport.write(data) pass factory = Factory() factory.protocol = Transfer reactor.listenTCP(9999,factory) reactor.run()
完成 !
總結
以上是生活随笔為你收集整理的使用Python的twisted和socket模块实现端口的负载分发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 3.10 新特性
- 下一篇: 浏览器是如何工作的?(转载)