RG5*_*RG5 18 python python-asyncio
我正在学习python 3 asyncio库,我遇到了一个小问题.我正在尝试从python文档调整EchoServer示例以提示用户输入,而不是仅回显客户端发送的内容.
我认为它就像添加对input()的调用一样简单,但当然input()将阻塞,直到有用户输入导致问题.
理想情况下,即使服务器没有"说",我也希望继续从客户端接收数据.有点像聊天客户端,每个连接与服务器聊天.我希望能够切换到每个单独的连接,并根据需要从stdin发送输入.几乎像一个P2P聊天客户端.
请考虑以下修改的EchoServer代码:
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))
reply = input()
print('Send: {!r}'.format(reply))
self.transport.write(reply.encode())
#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()
Run Code Online (Sandbox Code Playgroud)
我如何在服务器端获取输入格式stdin,并指定在连接客户端仍然接收输入的同时将其发送到哪个连接?
dan*_*ano 12
您可以使用loop.add_reader
调度回调在数据可用时运行sys.stdin
,然后使用an asyncio.Queue
将收到的stdin数据传递给您的data_received
方法:
import sys
import asyncio
def got_stdin_data(q):
asyncio.async(q.put(sys.stdin.readline()))
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))
fut = asyncio.async(q.get())
fut.add_done_callback(self.write_reply)
def write_reply(self, fut):
reply = fut.result()
print('Send: {!r}'.format(reply))
self.transport.write(reply.encode())
#print('Close the client socket')
#self.transport.close()
q = asyncio.Queue()
loop = asyncio.get_event_loop()
loop.add_reader(sys.stdin, got_stdin_data, q)
# 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()
Run Code Online (Sandbox Code Playgroud)
唯一棘手的一点是我们如何调用Queue.put
/ Queue.get
方法; 它们都是协同程序,yield from
在回调或Protocol
实例方法中无法调用.相反,我们只是使用事件循环来安排它们asyncio.async
,然后使用该add_done_callback
方法来处理我们从get()
调用中检索的回复.
归档时间: |
|
查看次数: |
5761 次 |
最近记录: |