Для Python3.5+
Клиент вебсокетов
aiohttp работает с вебсокетами с коробки.
Клиент должен использовать метод aiohttp.ClientSession.ws_connect() для установления вебсокет-соединения. Он принимает в качестве первого обязательного параметра урл сервера и возвращает ClientWebSocketResponse объект с помощью которого Вы можете общаться с сервером используя методы этого объекта:
Клиент должен использовать метод aiohttp.ClientSession.ws_connect() для установления вебсокет-соединения. Он принимает в качестве первого обязательного параметра урл сервера и возвращает ClientWebSocketResponse объект с помощью которого Вы можете общаться с сервером используя методы этого объекта:
session = aiohttp.ClientSession()
async with session.ws_connect('http://example.org/websocket') as ws:
async for msg in ws:
if msg.tp == aiohttp.MsgType.text:
if msg.data == 'close cmd':
await ws.close()
break
else:
ws.send_str(msg.data + '/answer')
elif msg.tp == aiohttp.MsgType.closed:
break
elif msg.tp == aiohttp.MsgType.error:
break
Вы также можете установить вебсокет-соединения без инстанса ClientSession с помощью aiohttp.ws_connect():
async with aiohttp.ws_connect('http://example.org/websocket') as ws:
…
Как для чтения (например await ws.receive() или async for msg in ws:) так и для записи Вы должны использовать только одну задачу, но асинхронная отправка данных (например ws.send_str('data')) может быть в нескольких задачах
ws_connect
Для подключения к вебсокет серверу нужно использовать aiohttp.ws_connect () или aiohttp.ClientSession.ws_connect().
coroutine aiohttp.ws_connect(
url, *, protocols=(), timeout=10.0, connector=None,
auth=None, ws_response_class=ClientWebSocketResponse,
autoclose=True, autoping=True, loop=None, origin=None)
Эта функция создает вебсокет-соединение, проверяет ответ и возвращает объект ClientWebSocketResponse. В случае ошибки будет вызвано WSServerHandshakeError исключение.
Параметры:
- url (str) – урл вебсокет-сервера
- protocols (tuple) – протоколы вебсокета
- timeout (float) – таймаут для чтения вебсокета. По-умолчанию 10 секунд
- connector (obj) – коннектор - объект TCPConnector
- ws_response_class – класс реализации получения ответа. По-умолчанию ClientWebSocketResponse
- autoclose (bool) – автоматически закрыть вебсокет соединение при получении сообщения о закрытии. Если установлено в False, то нужно обрабатывать вручную. По-умолчанию True
import asyncio
import aiohttp
async def test(autoclose):
ws = await aiohttp.ws_connect('ws://127.0.0.1:8888', autoclose=autoclose)
ws.send_str('close me') # отправляем серверу 'close me'
# на сервере прописана такая логика
# tornado websocket server
# if message == 'close me':
# self.close()
r = await ws.receive() # ждем ответа
print(autoclose, ws.closed)
if not ws.closed and r.tp == 8: # если соединение не закрыто
#и тип сообщение равен 8 (8 говорит о MSG_CLOSE)
print("autoclose = False")
await ws.close()
loop = asyncio.get_event_loop()
tasks = [
test(True),
test(False)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
- autoping (bool) – автоматически отправлять понг на пинг от сервера
- auth (aiohttp.helpers.BasicAuth) – BasicAuth кортеж с именованными полями который представляет HTTP Basic Authorization
- loop – событийный цикл используемый для обработки HTTP запросов. Если loop=None, то будет вызвано asyncio.get_event_loop() для получения событийного цикла по-умолчанию, но мы настоятельно рекомендуем явно указывать событийный цикл.
- origin (str) – Заголовки происхождения (источника) которые будут переданы на сервер
ClientWebSocketResponse
class aiohttp.ClientWebSocketResponse
Класс для обработки вебсокетов на стороне клиента
Класс для обработки вебсокетов на стороне клиента
- closed — свойство только для чтения. True если закрыто соединение (было вызвано close), иначе — False. Смотреть предыдущий пример
- protocol — субпротоколы вебсокет-соединения выбранные после вызова start(). None если сервер и клиент не используют одинаковые подпротоколы
- exception() - возвращает исключение если оно было при соединении, иначе None
Давайте рассмотрим пример где на стороне сервера произошла какая-то ошибка, например
при этом соединение не будет разорвано и клиент будет ожидать ответа далее, поэтому чтобы отлавливать ошибки и ghfdbkmyj обрабатывать их, (например, aiohttp.errors.ServerDisconnectedError) можно делать так:
. . . # tornado
self.write_message(1/0)
. . .
при этом соединение не будет разорвано и клиент будет ожидать ответа далее, поэтому чтобы отлавливать ошибки и ghfdbkmyj обрабатывать их, (например, aiohttp.errors.ServerDisconnectedError) можно делать так:
async def test():
session = aiohttp.ClientSession()
async with session.ws_connect('ws://127.0.0.1:8888') as ws:
ws.send_str('hello')
async for msg in ws:
raise ws.exception()
- ping(message=b'') — отправить пинг (MSG_PING). message — опциональный параметр для указания полезной нагрузки пинг-сообщения. Можно передавать str (будет побайтно закодирован в UTF-8) или bytes.
- send_str(data) — отправить информацию как MSG_TEXT сообщение. Информацию нужно передавать в метод первым неименованным параметром строкой (тип str). Если будет передана не строка будет вызвано исключение TypeError.
- send_bytes(data) - отправить информацию как MSG_BYTE сообщение. Информацию нужно передавать в метод первым неименованным параметром с типом bytes, bytearray или memoryview. Если будет передан объект иного типа будет вызвано исключение TypeError.
- coroutine close(*, code=1000, message=b'') — coroutine что инициирует закрытие соединения отправит MSG_CLOSE сообщение и ждет ответа от сервера.
Рассмотрим пример где мы подключаемся к серверу и он, после первого сообщения уходит в бесконечный цикл
так как метод close() ждет ответа от сервера, то мы никогда не закроем соединение. Для того чтобы избежать такой ситуации мы можем обернуть close() в asyncio.wait() или asyncio.wait_for():
# tornado
def on_message(self, message):
while True:
self.write_message(':-||')
так как метод close() ждет ответа от сервера, то мы никогда не закроем соединение. Для того чтобы избежать такой ситуации мы можем обернуть close() в asyncio.wait() или asyncio.wait_for():
import asyncio
import aiohttp
@asyncio.coroutine
def test():
session = aiohttp.ClientSession()
ws = yield from (session.ws_connect('ws://127.0.0.1:8888'))
# подключимся к серверу который после первого сообщения уходит в бесконечный цикл
# так как метод close() ждет подтверждения, то мы никога не закроем соединение
#
ws.send_bytes(bytes([0]))
try:
yield from asyncio.wait_for(ws.close(), 2) # ждем две секунды
except asyncio.TimeoutError:
print("Timeout")
finally:
session.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(test())
loop.close()
Метод поддерживает два необязательных параметра:
- code (int) — код закрытия соединения
- message() - указания полезной нагрузки понг-сообщения. Можно передавать str (будет побайтно закодирован в UTF-8) или bytes.
- coroutine receive() - ждет входящего сообщения и возвращает объект типа Message. Неявно обрабатывает MSG_PING, MSG_PONG и MSG_CLOSE ничего не возвращая. Это пинг-понг процесс что выполняет закрытие соединения.
Комментариев нет:
Отправить комментарий