#python-asyncio
#python-asyncio
Вопрос:
Итак, я могу довольно легко создать SSLSocket
в asyncio:
# Create a Socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.setblocking(False)
# Connect
await loop.sock_connect(sock, host_address) # type: ignore
# Create an SSL Context
ssl_context = ssl.create_default_context(cafile=PROXY_CA_BUNDLE)
...
# Wrap the SSL Context Around the Socket
def do_handshake(loop, sock, waiter):
sock_fd = sock.fileno()
try:
sock.do_handshake()
except ssl.SSLWantReadError:
loop.remove_reader(sock_fd)
loop.add_reader(sock_fd, do_handshake,
loop, sock, waiter)
return
except ssl.SSLWantWriteError:
loop.remove_writer(sock_fd)
loop.add_writer(sock_fd, do_handshake,
loop, sock, waiter)
return
loop.remove_reader(sock_fd)
loop.remove_writer(sock_fd)
waiter.set_result(None)
waiter = loop.create_future()
do_handshake(loop, sslconn, waiter)
await waiter
Проблема в том, что SSLSocket нарушает неблокирующий интерфейс исходной библиотеки сокетов, поэтому он больше не совместим с другими методами asyncio, такими как asyncio.sock_sendall
. Есть ли способ вместо этого обернуть сокет, чтобы он по-прежнему сохранял исходный интерфейс сокета?
Комментарии:
1. Почему вы пытаетесь использовать низкоуровневый
loop.remove_reader()
иloop.add_reader()
API вместо streams API? Например,loop.create_connection
поддерживает создание SSL-соединений — вы можете это использовать?2. К сожалению, я не могу использовать streams API; Мне нужно передать сокет в приложение Cython, которое ожидает сокет Python по умолчанию.
3. Ожидает ли приложение Cython блокирующий или неблокирующий сокет? Кроме того, если сокет ожидается приложением, зачем вообще подключать его к циклу событий asyncio?
4. Неблокирующее гнездо (как указано выше). Usecase в основном использует asyncio для создания прокси-соединения (HTTP), затем нужен исходный сокет для протокола cython.
5. Если единственная проблема заключается в том, что asyncio не работает с обернутым сокетом, тогда я бы вызвал высокоуровневый API и затем получил используемый им сокет. Например, создайте подкласс
SSLContext
и предоставьтеwrap_socket
impl, который сохраняетSSLSocket
созданноеsuper().wrap_socket(...)
в выбранном вами месте. После вызоваopen_connection
сssl=<your context>
помощью и настройки прокси-сервера вы могли бы извлечьSSLSocket
и передать его Cython.