You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
75 lines
2.2 KiB
75 lines
2.2 KiB
# Example of a HTTPS client working with non-blocking sockets.
|
|
#
|
|
# Non-blocking SSL streams works differently in MicroPython compared to CPython. In
|
|
# CPython a write to an SSLSocket may raise ssl.SSLWantReadError. In MicroPython an
|
|
# SSLSocket behaves like a normal socket/stream and can be polled for reading/writing.
|
|
|
|
from errno import EINPROGRESS
|
|
import select
|
|
import socket
|
|
import ssl
|
|
|
|
|
|
def connect_nonblocking(sock, addr):
|
|
sock.setblocking(False)
|
|
try:
|
|
sock.connect(addr)
|
|
except OSError as er:
|
|
if er.errno != EINPROGRESS:
|
|
raise er
|
|
|
|
|
|
def write_nonblocking(poller, sock, data):
|
|
poller.register(sock, select.POLLOUT)
|
|
while data:
|
|
poller.poll()
|
|
n = sock.write(data)
|
|
print("Wrote:", n)
|
|
if n is not None:
|
|
data = data[n:]
|
|
|
|
|
|
def read_nonblocking(poller, sock, n):
|
|
poller.register(sock, select.POLLIN)
|
|
poller.poll()
|
|
data = sock.read(n)
|
|
print("Read:", len(data))
|
|
return data
|
|
|
|
|
|
def main(url):
|
|
# Split the given URL into components.
|
|
proto, _, host, path = url.split(b"/", 3)
|
|
assert proto == b"https:"
|
|
|
|
# Note: this getaddrinfo() call is blocking!
|
|
ai = socket.getaddrinfo(host, 443)[0]
|
|
addr = ai[-1]
|
|
print("Connect address:", addr)
|
|
|
|
# Create a TCP socket and connect to the server in non-blocking mode.
|
|
sock = socket.socket(ai[0], ai[1], ai[2])
|
|
connect_nonblocking(sock, addr)
|
|
|
|
# Wrap the TCP socket in an SSL stream in non-blocking mode.
|
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
sock = ctx.wrap_socket(sock, server_hostname=host, do_handshake_on_connect=False)
|
|
sock.setblocking(False)
|
|
|
|
# Create an object to poll the SSL stream for readability/writability.
|
|
poller = select.poll()
|
|
|
|
# Send the HTTP request on the SSL stream.
|
|
request = b"GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host)
|
|
write_nonblocking(poller, sock, request)
|
|
|
|
# Receive the HTTP response from the SSL stream.
|
|
response = read_nonblocking(poller, sock, 1000)
|
|
for line in response.split(b"\n"):
|
|
print(line)
|
|
|
|
# Close the SSL stream. This will also close the underlying TCP socket.
|
|
sock.close()
|
|
|
|
|
|
main(b"https://micropython.org/ks/test.html")
|
|
|