Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5119800
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2015-07-24 13:50:30

原文链接 

最近迷上了Twisted。

本来是比较喜欢用gevent的,不过gevent不能和pypy很好地结合,在对性能要求比较高的地方有点慢,能明显感觉到建立连接的时候有卡顿。

后来嘛,试验了一下evenlet,因为其epoll部分没有依赖C的库或代码,可以在pypy下跑,但是在pypy下表现平平,估计原因是greenlet,做得太通用了,肯定就以性能为代价了,记得它的实现原理是拷贝栈和恢复栈。

再后来嘛,Twisted上阵了,做hello world测试的时候,如果用CPython驱动它,性能确实比gevent差很多,大概只有gevent的三分之二。上了pypy后直接飙升到gevent的两倍,和erlang的效率差不多。

再后来嘛,用twisted草草实现了一个垃圾级别的sock5代理服务器,用pypy来驱动的话,在1MB/s的传输速率下,CPU占用率和我用erlang写的版本基本一样。如果用CPython占用就高很多。

erlang也研究过一段时间,因为它对字符串处理的支持薄弱,所以暂时放弃了,不知到有木有大神对erlang的字符串处理有相关经验?如果能重拾erlang也不错的。

上个twisted实现的垃圾级别的sock5代理服务器代码。pipe部分实现得不好,没法作流量控制,以后再研究。


  1. import struct, socket
  2. from twisted.internet import reactor
  3. from twisted.names import client as names_client
  4. from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol
  5. from twisted.internet.endpoints import TCP4ServerEndpoint
  6.  
  7. class TCPPipe(Protocol):
  8.     def __init__(self, client):
  9.         self.client = client
  10.  
  11.     def connectionMade(self):
  12.         try:
  13.             self.client.fsm.send(self)
  14.         except StopIteration:
  15.             pass
  16.  
  17.     def dataReceived(self, data):
  18.         self.client.transport.write(data)
  19.  
  20.     def connectionLost(self, reason):
  21.         self.client.transport.loseConnection()
  22.  
  23.  
  24. class TcpPipeFactory(ClientFactory):
  25.     def __init__(self, client):
  26.         self.client = client
  27.  
  28.     def buildProtocol(self, addr):
  29.         return TCPPipe(self.client)
  30.  
  31. class Socks(Protocol):
  32.  
  33.     def __init__(self):
  34.         self.fsm = self.state_version("")
  35.         self.fsm.next()
  36.  
  37.     def connectionMade(self):
  38.         pass
  39.  
  40.     def connectionLost(self, reason):
  41.         print reason
  42.  
  43.     def dataReceived(self, data):
  44.         try:
  45.             self.fsm.send(data)
  46.         except StopIteration:
  47.             pass
  48.         except:
  49.             self.transport.loseConnection()
  50.  
  51.     def state_version(self, buff):
  52.         while len(buff) < 1:
  53.             buff += yield
  54.         version, buff = ord(buff[0]), buff[1:]
  55.         if version == 5:
  56.             self.fsm = self.state_sock5(buff)
  57.             self.fsm.next()
  58.         else:
  59.             self.transport.abortConnection()
  60.  
  61.     def state_sock5(self, buff):
  62.         while len(buff) < 1:
  63.             buff += yield
  64.         ncommands, buff = ord(buff[0]), buff[1:]
  65.  
  66.         while len(buff) < ncommands:
  67.             buff += yield
  68.         commands, buff = buff[:ncommands], buff[ncommands:]
  69.         if '\x00' not in commands:
  70.             self.transport.write('\x05\x01\xFF')
  71.             return
  72.         self.transport.write('\x05\x00')
  73.  
  74.         while len(buff) < 4:
  75.             buff += yield
  76.         data, buff = buff[:4], buff[4:]
  77.         if data[0] != '0x05' and data[2] != '\x00':
  78.             self.transport.write('\x05\x07\x00')
  79.             return
  80.         command = data[1]
  81.         atype = data[3]
  82.         if atype == '\x01':
  83.             while len(buff) < 6:
  84.                 buff += yield
  85.             data, buff = buff[:6], buff[6:]
  86.             target_IP, target_Port = struct.unpack('!4sH', data)
  87.             target_IP = socket.inet_ntoa(target_IP)
  88.         elif atype == '\x03':
  89.             while len(buff) < 1:
  90.                 buff += yield
  91.             hostnameLen, buff = ord(buff[:1]), buff[1:]
  92.             while len(buff) < hostnameLen+2:
  93.                 buff += yield
  94.             data, buff = buff[:hostnameLen+2], buff[hostnameLen+2:]
  95.             target_hostname, target_Port = struct.unpack('!%dsH' % hostnameLen, data)
  96.             self.transport.stopReading()
  97.             d = names_client.getHostByName(target_hostname)
  98.             d.addCallbacks(lambda ip: self.fsm.send(ip), lambda err: self.transport.abortConnection())
  99.             target_IP = yield
  100.             self.transport.startReading()
  101.         else:
  102.             self.transport.write('\x05\x08\x00')
  103.             return
  104.         if command == '\x01':
  105.             print (target_IP, target_Port)
  106.             self.transport.stopReading()
  107.             reactor.connectTCP(target_IP, target_Port, TcpPipeFactory(self))
  108.             remote = yield
  109.             self.transport.startReading()
  110.             remote.transport.write(buff)
  111.             peer = remote.transport.getPeer()
  112.             reply = '\x05\x00\x00\x01' + socket.inet_aton(peer.host) + struct.pack('!H', peer.port)
  113.             self.transport.write(reply)
  114.             self.remote = remote
  115.             self.fsm = self.state_5_pipe(buff)
  116.             self.fsm.next()
  117.         else:
  118.             client_socket.sendall('\x05\x07\x00')
  119.             return
  120.  
  121.     def state_5_pipe(self, buff):
  122.         remote = self.remote
  123.  
  124.         while True:
  125.             buff = yield
  126.             remote.transport.write(buff)
  127.  
  128.  
  129.     def connectionLost(self, reason):
  130.         if hasattr(self, "remote"):
  131.             self.remote.transport.loseConnection()
  132.  
  133. class SocksFactory(ServerFactory):
  134.  
  135.     def buildProtocol(self, addr):
  136.         return Socks()
  137.  
  138. endpoint = TCP4ServerEndpoint(reactor, 8888, backlog=10000)
  139. endpoint.listen(SocksFactory())
  140. reactor.run()

阅读(1692) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~