import asyncore import socket import sys class Receiver(asyncore.dispatcher_with_send): def __init__(self,sock,remote_ip,remote_port): asyncore.dispatcher_with_send.__init__(self,sock=sock) self.buffer="" self.max_buffer_size=1024000 self.remote_ip=remote_ip self.remote_port=remote_port sender_sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: sender_sock.connect((self.remote_ip,self.remote_port)) print 'connected to %s:%d' % (self.remote_ip,self.remote_port) self.sender=Sender(self,sender_sock) except Exception,e: print e self.close() def handle_read(self): data = self.recv(10240) if data: try: self.sender.sendall(data) print '%4d bytes' % sys.getsizeof(data) except Exception, e: print e def handle_close(self): print "closing receiver..." try: self.close() self.sender.close() except Exception, e: print e class Sender(asyncore.dispatcher_with_send): def __init__(self, receiver, sender_sock): asyncore.dispatcher_with_send.__init__(self,sender_sock) self.receiver = receiver def handle_read(self): try: data = self.recv(10240) self.receiver.sendall(data) print '%4d bytes' % sys.getsizeof(data) except Exception,e: print e self.close() def handle_close(self): print "closing sender..." try: self.close() self.receiver.close() pass except Exception, e: print e class ProxyServer(asyncore.dispatcher): def __init__(self, host, local_port,remote_ip,remote_port): asyncore.dispatcher.__init__(self) self.local_port=local_port self.remote_ip=remote_ip self.remote_port=remote_port self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((host, local_port)) #self.listen(5) #print 'listen...' def handle_accept(self): pair = self.accept() if pair is not None: sock, addr = pair print '%s connected' % repr(addr) handler = Receiver(sock,self.remote_ip,self.remote_port) return handler def run(self): print "proxy server running..." self.listen(5) print 'local port=',self.local_port print 'remote ip=',self.remote_ip print 'remote port=',self.remote_port if __name__ =='__main__': try: ''' import getopt opts, args = getopt.getopt(sys.argv[1:], "l:a:p:") for op,value in opts: if op in ('-l'): listenPort=int(value) elif op in ('-a'): remote_ip=value elif op in ('-p'): remote_port=int(value) else: sys.exit(0) ''' import optparse parser = optparse.OptionParser() parser.add_option( '-l','--local-port', type='int',dest='local_port',default=80, help='Local port') parser.add_option( '-r','--remote-ip', dest='remote_ip', help='Remote IP address') parser.add_option( '-p','--remote-port', type='int',dest='remote_port',default=80, help='Remote port') options, args = parser.parse_args() except Exception,e: print e try: server = ProxyServer('0.0.0.0', options.local_port,options.remote_ip,options.remote_port) #server2 = ProxyServer('0.0.0.0', 6666,options.remote_ip,options.remote_port) server.run() #server2.run() asyncore.loop() except Exception, e: print e
参考资料:
Asynchronous port forwarding (Python recipe)
经测试,在数据量大的情况下经常出现error 10035.
Asynchronous port forwarding (Python recipe)才是稳定的!
import socket,asyncore class forwarder(asyncore.dispatcher): def __init__(self, ip, port, remoteip,remoteport,backlog=5): asyncore.dispatcher.__init__(self) self.remoteip=remoteip self.remoteport=remoteport self.create_socket(socket.AF_INET,socket.SOCK_STREAM) self.set_reuse_addr() self.bind((ip,port)) self.listen(backlog) def handle_accept(self): conn, addr = self.accept() # print '--- Connect --- ' sender(receiver(conn),self.remoteip,self.remoteport) class receiver(asyncore.dispatcher): def __init__(self,conn): asyncore.dispatcher.__init__(self,conn) self.from_remote_buffer='' self.to_remote_buffer='' self.sender=None def handle_connect(self): pass def handle_read(self): read = self.recv(4096) # print '%04i -->'%len(read) self.from_remote_buffer += read def writable(self): return (len(self.to_remote_buffer) > 0) def handle_write(self): sent = self.send(self.to_remote_buffer) # print '%04i <--'%sent self.to_remote_buffer = self.to_remote_buffer[sent:] def handle_close(self): self.close() if self.sender: self.sender.close() class sender(asyncore.dispatcher): def __init__(self, receiver, remoteaddr,remoteport): asyncore.dispatcher.__init__(self) self.receiver=receiver receiver.sender=self self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((remoteaddr, remoteport)) def handle_connect(self): pass def handle_read(self): read = self.recv(4096) # print '<-- %04i'%len(read) self.receiver.to_remote_buffer += read def writable(self): return (len(self.receiver.from_remote_buffer) > 0) def handle_write(self): sent = self.send(self.receiver.from_remote_buffer) # print '--> %04i'%sent self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:] def handle_close(self): self.close() self.receiver.close() if __name__=='__main__': import optparse parser = optparse.OptionParser() parser.add_option( '-l','--local-ip', dest='local_ip',default='127.0.0.1', help='Local IP address to bind to') parser.add_option( '-p','--local-port', type='int',dest='local_port',default=80, help='Local port to bind to') parser.add_option( '-r','--remote-ip',dest='remote_ip', help='Local IP address to bind to') parser.add_option( '-P','--remote-port', type='int',dest='remote_port',default=80, help='Remote port to bind to') options, args = parser.parse_args() forwarder(options.local_ip,options.local_port,options.remote_ip,options.remote_port) asyncore.loop()