我玩socket
。我有点想通了正常的版本,现在我想写一个异步的。例如一个简单的回显服务器。有一个代码:
async def _run(self) -> None:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((settings.HOST, settings.PORT))
self.server_socket.listen(8)
self.server_socket.setblocking(False)
loop = asyncio.get_event_loop()
while True:
client, address = await loop.sock_accept(self.server_socket)
print(f"Connected {address}")
loop.create_task(self.handle_client(client, address))
async def handle_client(self, client_socket: socket.socket, address: tuple) -> None:
while True:
data = client_socket.recv(1024).decode(encoding=settings.ENCODING) # BlockingIOError: [WinError 10035] Операция на незаблокированном сокете не может быть завершена немедленно
if not data:
break
client_socket.send(data.upper().encode(encoding=settings.ENCODING))
print(data)
它因错误而中断:
BlockingIOError: [WinError 10035] Операция на незаблокированном сокете не может быть завершена немедленно
我大致理解为什么:需要self.server_socket.setblocking(False)
实现异步并且客户端还没有读取过去的数据或者根本还没有准备好。client_socket.recv
如果你把before time.sleep
,那么一切都开始工作,但这显然不是一个解决方案。
我怎样才能异步(以便在那一刻处理其他客户端)等待我可以读/写东西的那一刻?
PS我知道asyncore
,但我想从头开始写一切,并从内部了解一切是如何运作的
如果将示例替换为 ,则可以使示例正常
client_socket.recv(1024)
工作
(await asyncio.get_event_loop().sock_recv(client_socket, 1024))
。(最好去掉一个循环)
里面发生了什么——你可以在CPython 源代码
中看到 简而言之,操作系统为文件描述符(它也存在于套接字上)提供了接收事件的能力,包括可读性事件。
这是使用选择器 (Poll, Epoll, ...) 完成的。在这种情况下,选择器会传递要监视的文件描述符和事件。