我想更好地了解python中的asyncio,所以决定只使用基本实用程序(如socket和asyncio)编写一个简单的http代理服务器。 这是我的代码
import asyncio
import socket
BUFFER = 4096
class ProxyServer:
def __init__(self):
self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listener.bind(("192.168.1.6", 80))
self.listener.listen()
async def invoke(self, loop):
try:
while 1:
conn, addr = self.listener.accept()
await self.process_new_conn(conn, loop)
except KeyboardInterrupt:
loop.stop()
print("Finishing...")
async def process_new_conn(self, conn, loop):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sender:
data = await loop.sock_recv(conn, BUFFER)
await loop.sock_connect(sender, (host, port))
sender.send(data)
response = await loop.sock_recv(sender, BUFFER)
conn.send(response)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
try:
ps = ProxyServer()
loop.run_until_complete(ps.invoke(loop))
except OSError:
print("80 port is being used.")
finally:
loop.close()
据我了解,loop.run_until_complete
将我的coro添加到循环队列并在某些时候执行它。当我调用await self.process_new_conn(conn, loop)
循环时,将此coro添加到其队列中。我的问题是如何将队列放入循环中?我的意思是它看起来像process_new_conn
中的代码被执行但是另一个套接字什么都没有收到,但是当我尝试键入类似这样的loop.run_until_complete(self.process_new_conn(conn, loop))
时,它可以工作(运行时错误但仍然存在)。看起来应该有另一种方法,但我无法找到它。
import asyncio
import socket
from select import select
BUFFER = 4096
class ProxyServer:
def __init__(self):
self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listener.bind(("localhost", 80))
self.listener.listen()
self.loop = asyncio.get_event_loop()
def invoke(self):
try:
self.loop.run_until_complete(self.accept_connection())
except KeyboardInterrupt:
self.loop.stop()
self.loop.close()
print("Finishing...")
async def accept_connection(self):
while 1:
read, _, _ = select([self.listener], [], [], 0.1)
if read:
conn, addr = self.listener.accept()
await self.process_new_conn(conn)
async def process_new_conn(self, conn):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sender:
data = await self.loop.sock_recv(conn, BUFFER)
await self.loop.sock_connect(sender, (host, port))
sender.send(data)
response = await self.loop.sock_recv(sender, BUFFER)
await self.loop.sock_sendall(conn, response)
if __name__ == "__main__":
try:
ps = ProxyServer()
ps.invoke()
except OSError:
print("80 port is being used.")
据我所知:使用await
我们说一个循环,coro应该被放入一个队列并且可能被中断(这让一个循环在wordd await
处切换当前coro)。这段视频给了我很多帮助https://www.youtube.com/watch?v=m28fiN9y_r8&t=679s