#python #python-3.x #sockets #python-asyncio
#python #python-3.x #сокеты #python-asyncio
Вопрос:
Я писал код для сервера asyncio на моем Raspberry pi 4. Когда я кодировал клиента и выполнял тестовый запуск с моим серверным классом, он возвращает:
Traceback (most recent call last):
File "C:Users####Documentsrpiswrclient.py", line 23, in <module>
asyncio.run(client_run())
File "C:Users####AppDataLocalProgramsPythonPython39libasynciorunners.py", line 44, in run
return loop.run_until_complete(main)
File "C:Users####AppDataLocalProgramsPythonPython39libasynciobase_events.py", line 642, in run_until_complete
return future.result()
File "C:Users####Documentsrpiswrclient.py", line 18, in client_run
await client.connect(("192.168.0.11", 56500))
File "C:Users####Documentsrpiswraserver__init__.py", line 11, in connect
print(f"Connecting as {self.s.getsockname()}")
OSError: [WinError 10022] An invalid argument was supplied
Я просмотрел ошибку, и существенного результата нет. Вот почему я спрашиваю об этом. Я перечислю свой код ниже:
init.py (в каталоге aserver):
import asyncio, socket
class Client:
def __init__(self):
pass
async def connect(self, addr):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.setblocking(False)
print(f"Connecting as {self.s.getsockname()}")
self.s.connect(addr)
async def recv(self,buf_size):
data = buf_size
print(f"Recieved {data.decode()} in byte data")
async def close_conn(self):
print(f"Closed connection with server")
self.s.close()
async def send_bytes(self, data:bytes):
self.s.sendall(data)
print(f"Sent {data.decode()} in byte format")
class Server:
"""Implement handle function or decorate a function with @Server.handler(<Server>)"""
def __init__(self, addr):
self.addr = addr
async def start_server(self, handler_method):
self.server = await asyncio.start_server(handler_method, self.addr[0], self.addr[1])
self.addr = self.server.sockets[0].getsockname()
print(f"Serving on {self.addr}")
async with self.server:
await self.server.serve_forever()
client.py (здесь возникают проблемы):
from aserver import Client
import asyncio
client = Client()
async def client_run():
await client.connect(("192.168.0.11", 56500))
await client.send_bytes(b'Hi Echo Server!')
await client.recv(1024)
await client.close_conn()
asyncio.run(client_run())
server.py (работает отлично):
import aserver as srv
from aserver import Server
import asyncio
server = srv.Server(["192.168.0.11", 56500])
async def echo_server(reader, writer):
data = await reader.read(1024)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"Recieved {message} from addr")
print(f"Echoing {message} back")
writer.write(data)
await writer.drain()
print(f"Closing connection with {addr}")
writer.close()
asyncio.run(server.start_server(echo_server))
Почему возникает эта ошибка? Как мне это исправить? Любой ответ будет оценен по достоинству. Я был бы рад, если бы вы могли исправить мой код там, где вы видите проблему.
Редактировать:
Ответил @user4815162342, но спасибо всем, кто внес свой вклад!
Комментарии:
1. Ваш клиентский код по-прежнему неверен в том смысле, что он использует блокирующий код внутри
async def
, который может и будет блокировать весь цикл событий.2. @user4815162342 Извините, но я действительно не понимаю, как остановить блокировку. Есть ли шанс, что я мог бы получить пример того, как прекратить блокировать цикл событий?
3. Как я уже говорил вам в предыдущем вопросе, вы можете использовать
asyncio.open_connection
вместо необработанных сокетов. С блокирующими сокетами вы получите код, который просто выглядит асинхронным, но не использует асинхронные вызовы под капотом и, следовательно, не получает никаких преимуществ от asyncio.