srj*_*jio 11 python sockets python-asyncio
我想使用asyncio协同程序而不是多线程来重新实现我的代码.
server.py
def handle_client(client):
request = None
while request != 'quit':
request = client.recv(255).decode('utf8')
response = cmd.run(request)
client.send(response.encode('utf8'))
client.close()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 15555))
server.listen(8)
try:
while True:
client, _ = server.accept()
threading.Thread(target=handle_client, args=(client,)).start()
except KeyboardInterrupt:
server.close()
Run Code Online (Sandbox Code Playgroud)
client.py
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect(('localhost', 15555))
request = None
try:
while request != 'quit':
request = input('>> ')
if request:
server.send(request.encode('utf8'))
response = server.recv(255).decode('utf8')
print(response)
except KeyboardInterrupt:
server.close()
Run Code Online (Sandbox Code Playgroud)
我知道有一些适当的异步网络库可以做到这一点.但我只是想在这种情况下只使用asyncio核心库,以便更好地理解它.
在处理客户端定义之前只添加async关键字真是太好了......这里有一段似乎有效的代码,但我仍然对实现感到困惑.
asyncio_server.py
def handle_client(client):
request = None
while request != 'quit':
request = client.recv(255).decode('utf8')
response = cmd.run(request)
client.send(response.encode('utf8'))
client.close()
def run_server(server):
client, _ = server.accept()
handle_client(client)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 15555))
server.listen(8)
loop = asyncio.get_event_loop()
asyncio.async(run_server(server))
try:
loop.run_forever()
except KeyboardInterrupt:
server.close()
Run Code Online (Sandbox Code Playgroud)
如何以最佳方式调整此方法并使用async等待关键字.
use*_*342 14
线程代码的最接近的字面翻译将像以前一样创建套接字,并使用asyncio
低级套接字操作来实现服务器.这是一个例子,坚持更相关的服务器部分(客户端是单线程的,可能很好):
import asyncio, socket
async def handle_client(client):
request = None
while request != 'quit':
request = (await loop.sock_recv(client, 255)).decode('utf8')
response = str(eval(request)) + '\n'
await loop.sock_sendall(client, response.encode('utf8'))
client.close()
async def run_server():
while True:
client, _ = await loop.sock_accept(server)
loop.create_task(handle_client(client))
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 15555))
server.listen(8)
server.setblocking(False)
loop = asyncio.get_event_loop()
loop.run_until_complete(run_server())
Run Code Online (Sandbox Code Playgroud)
以上工作,但不是预期的使用方式asyncio
.虽然正确的抽象取决于应用程序,但您可能希望至少使用asyncio.start_server
而不是使用原始套接字.这大大减少了代码的行数:
async def handle_client(reader, writer):
request = None
while request != 'quit':
request = (await reader.read(255)).decode('utf8')
response = str(eval(request)) + '\n'
writer.write(response.encode('utf8'))
await writer.drain()
writer.close()
loop = asyncio.get_event_loop()
loop.create_task(asyncio.start_server(handle_client, 'localhost', 15555))
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)
有关其他详细信息,请参阅文档
Fox*_*Fox 12
我已阅读上面的答案和评论,试图弄清楚如何使用asyncio
套接字的库。正如 Python 中经常发生的那样,官方文档和示例是有用信息的最佳来源。我从支持文章末尾提供的示例中了解了Transports and Protocols
(低级 API)和Streams
(高级 API)。
例如,TCP Echo 服务器:
import asyncio
class EchoServerProtocol(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()
async def main():
# Get a reference to the event loop as we plan to use
# low-level APIs.
loop = asyncio.get_running_loop()
server = await loop.create_server(
lambda: EchoServerProtocol(),
'127.0.0.1', 8888)
async with server:
await server.serve_forever()
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)
和 TCP 回显客户端:
import asyncio
class EchoClientProtocol(asyncio.Protocol):
def __init__(self, message, on_con_lost):
self.message = message
self.on_con_lost = on_con_lost
def connection_made(self, transport):
transport.write(self.message.encode())
print('Data sent: {!r}'.format(self.message))
def data_received(self, data):
print('Data received: {!r}'.format(data.decode()))
def connection_lost(self, exc):
print('The server closed the connection')
self.on_con_lost.set_result(True)
async def main():
# Get a reference to the event loop as we plan to use
# low-level APIs.
loop = asyncio.get_running_loop()
on_con_lost = loop.create_future()
message = 'Hello World!'
transport, protocol = await loop.create_connection(
lambda: EchoClientProtocol(message, on_con_lost),
'127.0.0.1', 8888)
# Wait until the protocol signals that the connection
# is lost and close the transport.
try:
await on_con_lost
finally:
transport.close()
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)
希望它可以帮助那些寻找简单解释的人asyncio
。
归档时间: |
|
查看次数: |
15571 次 |
最近记录: |