异步:启动非阻塞侦听

2024-09-30 10:38:07 发布

您现在位置:Python中文网/ 问答频道 /正文

这是asyncio tutotial提供的基本tcp服务器:

import asyncio

class EchoServerClientProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        print('Connection from {}'.format(peername))
        self.transport = transport

    def data_received(self, data):
        message = data.decode()
        print('Data received: {!r}'.format(message))

        print('Send: {!r}'.format(message))
        self.transport.write(data)

        print('Close the client socket')
        self.transport.close()

loop = asyncio.get_event_loop()
# Each client connection will create a new protocol instance
coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)

# Serve requests until CTRL+c is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
    loop.run_forever()
except keyboardInterrupt:
    pass

# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()

就像所有(我发现的)其他例子一样,它使用阻塞循环。永远运行().
我该怎么做呢?
我已经尝试将启动服务器外包给一个函数,并用异步。异步(),但没有成功。 我错过了什么?在


Tags: runself服务器loopasyncioformatmessageclose
2条回答

您可以在调用loop.run_forever()之前安排多个并发异步任务。在

@asyncio.coroutine
def other_task_coroutine():
   pass  # do something

start_tcp_server_task = loop.create_task(loop.create_server(
    EchoServerClientProtocol, '127.0.0.1', 8888))

other_task = loop.create_task(other_task_coroutine())

self.run_forever()

当您调用loop.create_task(loop.create_server())loop.create_task(other_task_coroutine())时,实际上没有执行任何东西:创建一个协程对象并将其包装在任务中(将任务视为shell,将在任务中执行的代码的实例)。任务在创建时在循环中进行调度。在

循环将首先执行start_tcp_server_task(因为它是先安排的),直到阻塞IO事件挂起或被动套接字准备好侦听传入的连接。在

您可以将asyncio看作是一个运行在一个CPU上的不可抢占调度器:一旦第一个任务本身中断或完成,第二个任务将被执行。因此,当一个任务被执行时,另一个任务必须等到正在运行的任务完成或产生(或者在Python3.5中是“等待”)生成“(yield from client.read())或“waiting”(await client.read())意味着任务将手交给循环的调度器,直到client.read()可以执行(数据在套接字上可用)。在

一旦任务将控制权交还给循环,它就可以调度其他挂起的任务、处理传入的事件以及调度等待这些事件的任务。一旦无事可做,循环将执行进程的唯一阻塞调用:休眠,直到内核通知它事件已准备就绪。在

在这种情况下,您必须理解,当使用asyncio时,流程中运行的所有内容都必须异步运行,这样循环才能正常工作。不能在循环中使用多处理对象。在

注意,asyncio.async(coroutine(), loop=loop)等同于loop.create_task(coroutine())。在

此外,可以考虑在执行器中运行所需的内容。 例如。在

coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
async def execute(self, loop):
    await loop.run_in_executor(None, your_func_here, args: 

asyncio.async(execute(loop))
loop.run_forever()

executor将在executor中运行您想要的任何函数,这不会阻塞您的服务器。在

相关问题 更多 >

    热门问题