想想我有一个游戏,我正在为每个连接创建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()
答案 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()