如何为每个Asyncio连接创建一个类

时间:2018-02-10 08:35:45

标签: python python-3.x python-asyncio

想想我有一个游戏,我正在为每个连接创建Client类。客户端类存储用户首选项(如所选国家/地区)。当用户与游戏类断开连接时删除。我需要做这样的事情。我的代码:

import asyncio
import logging
import sys

SERVER_ADDRESS = ('localhost', 56346)

logging.basicConfig(
    level=logging.DEBUG,
    format='%(name)s: %(message)s',
    stream=sys.stderr,
)
log = logging.getLogger('main')

event_loop = asyncio.get_event_loop()

class Client():
    def __init__(this):
        this.something = ''

class Server(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport
        self.address = transport.get_extra_info('peername')
        self.log = logging.getLogger(
            'EchoServer_{}_{}'.format(*self.address)
        )
        self.log.debug('connection accepted')
    def data_received(self, data):
        self.log.debug('received {!r}'.format(data))
        self.transport.write(data)
        self.log.debug('sent {!r}'.format(data))
    def connection_lost(self, error):
        if error:
            self.log.error('ERROR: {}'.format(error))
        else:
            self.log.debug('closing')
        super().connection_lost(error)

factory = event_loop.create_server(Server, *SERVER_ADDRESS)
server = event_loop.run_until_complete(factory)
log.debug('starting up on {} port {}'.format(*SERVER_ADDRESS))
# Enter the event loop permanently to handle all connections.
try:
    event_loop.run_forever()
finally:
    log.debug('closing server')
    server.close()
    event_loop.run_until_complete(server.wait_closed())
    log.debug('closing event loop')
    event_loop.close()

1 个答案:

答案 0 :(得分:2)

您正在将Server作为protocol_factory传递给create_server,这意味着将为每个客户端创建一个新的Server实例。 (这个类的更好的名称就像ClientHandle。)

实例化客户端的逻辑位置在connection_made

self.client = Client()

根据您正在实施的协议,可能会要求客户授权自己。您将在到达data_received方法时填写客户的属性。另请注意,您没有为客户创建新的Client ,而是要创建新的Client 实例

使用基于流的API实现通信变得更加容易,它提供了与回调的协程映射。例如:

class Client:
    def __init__(self, name):
        self.name = name
        self.reader = self.writer = None

class App:
    def __init__(self):
        self._clients = set()

    async def new_client(self, reader, writer):
        addr = writer.get_extra_info('peername')
        writer.write(f'hello client from {addr}; please state your name\n'
                     .encode('utf-8'))
        name = (await reader.readline()).decode('utf-8').rstrip('\n')
        client = Client(name)
        client.reader = reader
        client.writer = writer
        writer.write(f'{name}, you are now represented as {client}\n'
                     .encode('utf-8'))
        # Add the client to the set of known clients. This would also
        # be the place to notify the application of the new client.
        # This coroutine could continue running and communicate
        # with the client without blocking the app.
        self._clients.add(client)

app = App()

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.start_server(app.new_client, *SERVER_ADDRESS, loop=loop))

# serve the requests until someone calls loop.quit()
loop.run_forever()