我试图用Python创建一个服务器来将流量从侦听端口转发到远程主机。我将呼叫侦听端口< - >远程托管代理,可能是 localhost:54321< - > ,某:2001 。
我需要运行XMLRPC服务器的另一个线程提供以下功能:
使用线程实现这一点非常简单。这就是我想出的:
import logging
import threading
import socket
class ProxyThread(threading.Thread):
""" Thread that serves as a transport proxy """
def __init__(self, server, client):
super(ProxyThread, self).__init__()
self.server = server # (host, port)
self.client = client # listening socket
self.kill_thread = threading.Event()
self.kill_client = threading.Event()
def connect_server(self):
try: # make connection to server
server = socket.create_connection(self.server, timeout=2)
except Exception as e:
return None
return server
def connect_client(self):
try: # accept connection from client
self.client.settimeout(1)
client, saddr = self.client.accept()
except socket.timeout:
return None
return client
def run(self):
client, server = None, None
def close():
if client:
client.close()
if server:
server.close()
return None, None
while not self.kill_thread.isSet():
if not server:
server = self.connect_server()
if not server:
time.sleep(2) # wait before retrying
continue
if not client:
client = self.connect_client()
if not client:
continue
while not (self.kill_client.isSet() or self.kill_thread.isSet()):
# read loop 0.1 timeout to check kill_client event
r, w, d = select.select([client, server], [], [], 0.1)
if client in r:
read = client.recv(1024)
if not read: # disconnected
break
server.sendall(read)
if server in r:
read = server.recv(1024)
if not read: # disconnected
break
client.sendall(read)
# close sockets and reset
client, server = close()
self.kill_client.clear()
# end of thread
close()
self.client.close()
然后从XMLRPC线程
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 0))
sock.listen(1)
proxy = ProxyThread(sock, ('somehost', 2001))
proxy.start()
# later ...
proxy.kill_client.set()
这样可行,但效率很低,并且引入了相当多的延迟。进一步使问题更加复杂的是,这台服务器将托管多达数百个并发代理,并且通过线程化,这将变成CPU占用并且延迟是不可接受的。
我正在研究异步框架,例如 twisted 和 asyncio ,但我无法弄清楚我将如何添加和控制从另一个线程(XMLRPC服务器)运行代理。任何人都可以帮助指导我朝正确的方向发展吗?