examples/network: Support IPv4 and IPv6 in HTTP client examples.
The main changes here are to pass the address family and socket type to `getaddrinfo()`, and then use the result of the address lookup when creating the socket, so it has the correct address family. This allows both IPv4 and IPv6 to work, because the socket is created with the correct AF_INETx type for the address. Also add some more comments to the examples to explain what's going on. Fixes issue #15580. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
d9a0fdda9a
commit
c8385ef75a
@ -1,16 +1,35 @@
|
|||||||
|
# Very simple HTTP client example:
|
||||||
|
# - Connects to a server.
|
||||||
|
# - Sends a HTTP request.
|
||||||
|
# - Reads the result.
|
||||||
|
#
|
||||||
|
# This example works in both MicroPython and CPython.
|
||||||
|
#
|
||||||
|
# To implement an HTTP client using less code, use mip to install the requests package:
|
||||||
|
# https://github.com/micropython/micropython-lib/tree/master/python-ecosys/requests
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
|
||||||
def main(use_stream=False):
|
# `addr_family` selects IPv4 vs IPv6: 0 means either, or use
|
||||||
s = socket.socket()
|
# socket.AF_INET or socket.AF_INET6 to select a particular one.
|
||||||
|
def main(domain, addr_family=0, use_stream=False):
|
||||||
ai = socket.getaddrinfo("google.com", 80)
|
# Lookup the server address, for the given family and socket type.
|
||||||
|
ai = socket.getaddrinfo(domain, 80, addr_family, socket.SOCK_STREAM)
|
||||||
print("Address infos:", ai)
|
print("Address infos:", ai)
|
||||||
addr = ai[0][-1]
|
|
||||||
|
|
||||||
|
# Select the first address.
|
||||||
|
ai = ai[0]
|
||||||
|
|
||||||
|
# Create a socket with the server's family, type and proto.
|
||||||
|
s = socket.socket(ai[0], ai[1], ai[2])
|
||||||
|
|
||||||
|
# Connect to the server.
|
||||||
|
addr = ai[-1]
|
||||||
print("Connect address:", addr)
|
print("Connect address:", addr)
|
||||||
s.connect(addr)
|
s.connect(addr)
|
||||||
|
|
||||||
|
# Send request and read response.
|
||||||
if use_stream:
|
if use_stream:
|
||||||
# MicroPython socket objects support stream (aka file) interface
|
# MicroPython socket objects support stream (aka file) interface
|
||||||
# directly, but the line below is needed for CPython.
|
# directly, but the line below is needed for CPython.
|
||||||
@ -21,7 +40,8 @@ def main(use_stream=False):
|
|||||||
s.send(b"GET / HTTP/1.0\r\n\r\n")
|
s.send(b"GET / HTTP/1.0\r\n\r\n")
|
||||||
print(s.recv(4096))
|
print(s.recv(4096))
|
||||||
|
|
||||||
|
# Close the socket.
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
|
||||||
main()
|
main("google.com")
|
||||||
|
|||||||
@ -1,20 +1,41 @@
|
|||||||
|
# Very simple HTTPS client example:
|
||||||
|
# - Connects to a server.
|
||||||
|
# - Upgrades the connection to a TLS connection.
|
||||||
|
# - Sends a HTTP request.
|
||||||
|
# - Reads the result.
|
||||||
|
#
|
||||||
|
# This example works in both MicroPython and CPython.
|
||||||
|
#
|
||||||
|
# To implement an HTTPS client using less code, use mip to install the requests package:
|
||||||
|
# https://github.com/micropython/micropython-lib/tree/master/python-ecosys/requests
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import ssl
|
import ssl
|
||||||
|
|
||||||
|
|
||||||
def main(use_stream=True):
|
# `addr_family` selects IPv4 vs IPv6: 0 means either, or use
|
||||||
s = socket.socket()
|
# socket.AF_INET or socket.AF_INET6 to select a particular one.
|
||||||
|
def main(domain, addr_family=0, use_stream=True):
|
||||||
ai = socket.getaddrinfo("google.com", 443)
|
# Lookup the server address, for the given family and socket type.
|
||||||
|
ai = socket.getaddrinfo(domain, 443, addr_family, socket.SOCK_STREAM)
|
||||||
print("Address infos:", ai)
|
print("Address infos:", ai)
|
||||||
addr = ai[0][-1]
|
|
||||||
|
|
||||||
|
# Select the first address.
|
||||||
|
ai = ai[0]
|
||||||
|
|
||||||
|
# Create a socket with the server's family, type and proto.
|
||||||
|
s = socket.socket(ai[0], ai[1], ai[2])
|
||||||
|
|
||||||
|
# Connect to the server.
|
||||||
|
addr = ai[-1]
|
||||||
print("Connect address:", addr)
|
print("Connect address:", addr)
|
||||||
s.connect(addr)
|
s.connect(addr)
|
||||||
|
|
||||||
|
# Upgrade the socket to a TLS connection.
|
||||||
s = ssl.wrap_socket(s)
|
s = ssl.wrap_socket(s)
|
||||||
print(s)
|
print(s)
|
||||||
|
|
||||||
|
# Send request and read response.
|
||||||
if use_stream:
|
if use_stream:
|
||||||
# Both CPython and MicroPython SSLSocket objects support read() and
|
# Both CPython and MicroPython SSLSocket objects support read() and
|
||||||
# write() methods.
|
# write() methods.
|
||||||
@ -26,7 +47,8 @@ def main(use_stream=True):
|
|||||||
s.send(b"GET / HTTP/1.0\r\n\r\n")
|
s.send(b"GET / HTTP/1.0\r\n\r\n")
|
||||||
print(s.recv(4096))
|
print(s.recv(4096))
|
||||||
|
|
||||||
|
# Close the socket.
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
|
||||||
main()
|
main("google.com")
|
||||||
|
|||||||
@ -37,13 +37,13 @@ def read_nonblocking(poller, sock, n):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def main(url):
|
def main(url, addr_family=0):
|
||||||
# Split the given URL into components.
|
# Split the given URL into components.
|
||||||
proto, _, host, path = url.split(b"/", 3)
|
proto, _, host, path = url.split(b"/", 3)
|
||||||
assert proto == b"https:"
|
assert proto == b"https:"
|
||||||
|
|
||||||
# Note: this getaddrinfo() call is blocking!
|
# Note: this getaddrinfo() call is blocking!
|
||||||
ai = socket.getaddrinfo(host, 443)[0]
|
ai = socket.getaddrinfo(host, 443, addr_family, socket.SOCK_STREAM)[0]
|
||||||
addr = ai[-1]
|
addr = ai[-1]
|
||||||
print("Connect address:", addr)
|
print("Connect address:", addr)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user