usocket – socket module

This module implements a subset of the corresponding CPython module, as described below. For more information, please refer to the original CPython documentation: socket.

This module provides access to the BSD socket interface

Difference from CPython

In order to improve efficiency and consistency, the socket object in MicroPython directly implements the stream (class file) interface. In CPython, you need to use the makefile() method to convert the socket into a file-like object. MicroPython still supports this method (but no operation), so if it is compatible with CPython, be sure to use it.

Socket address format

The native socket address format of the usocket module is the opaque data type returned by the getaddrinfo function, which must be used to parse text addresses (including numeric addresses):

sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1]
# You must use getaddrinfo() even for numeric addresses
sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(addr)

Using getaddrinfo is the most effective (in terms of memory and processing power), and it is also a portable way to use addresses.

However, the socket module (note the difference from the native MicroPython usocket module described here) provides a CPython-compatible way to specify addresses using tuples, as described below. Please note that depending on the MicroPython port, the socket module can be built in or needs to be installed from micropython-lib (as in the case of "MicroPython Unix port"), and some ports still only accept numeric addresses in tuples Format and requires the use of the getaddrinfo function to resolve the domain name.

In general:

  • Always use getaddrinfo when writing portable applications.
  • If your port supports fast hacking and interactive use, the tuple address described below can be used as a shortcut.

The tuple address format of the socket module:

  • IPv4: (ipv4_address, port), where ipv4_address is a string with a dotted number IPv4 address, for example, "8.8.8.8", the port number and integer port number are in the range of 1-65535. Please note that domain names are not accepted as ipv4_address, they should be resolved first using usocket.getaddrinfo().

  • IPv6: (ipv6_address, port, flowinfo, scopeid), where ipv6_address is a string with a colon number IPv6 address, for example: "2001:db8::1", port is an integer port number in the range of 1-65535. flowinfo must be 0. scopeid is the interface scope identifier of the link local address. Please note that domain names are not accepted as ipv6_address, they should be resolved using usocket.getaddrinfo() first. The availability of IPv6 support depends on the MicroPython port.

Method

usocket.socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)

Create a new socket using the given address series, socket type and protocol number. Please note that in most cases there is no need to specify proto (not recommended because some MicroPython ports may omit the IPPROTO_ * constants). Instead, the type parameter will automatically select the required protocol:

# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)

usocket.getaddrinfo(host, port, af=0, type=0, proto=0, flags=0)

Convert the host / port parameter to a 5-tuple sequence, which contains all the necessary parameters for creating a socket to connect to the service. The parameters af, type and proto (which have the same meaning as the socket() function) can be used to filter which address is returned. If the parameter is not specified or is zero, all address combinations can be returned (requires filtering on the user side).

The resulting 5-tuple list has the following structure:

(family, type, proto, canonname, sockaddr)

The following example shows how to connect to a given URL:

s = usocket.socket()
# This assumes that if "type" is not specified, an address for
# SOCK_STREAM will be returned, which may be not true
s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1])

It is recommended to use filter parameters:

s = usocket.socket()
# Guaranteed to return an address which can be connect'ed to for
# stream operation.
s.connect(usocket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])

Difference with CPython

If this function fails, CPython will raise a socket.gaierror exception (subclass of OSError). MicroPython does not have socket.gaierror and directly raises OSError. Please note that the error number of getaddrinfo() forms a separate namespace and may not match the error number in the uerrno module. In order to distinguish getaddrinfo() errors, they are represented by negative numbers, while standard system errors are positive numbers (the error number can be accessed using the e.args[0] attribute from the exception object). The use of negative values ​​is a temporary detail and may change in the future.

usocket.inet_ntop(af, bin_addr)

Convert the binary network address bin_addr of a given address family af into a text representation:

>>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'

usocket.inet_pton(af, txt_addr)

Convert the text network address txt_addr of a given address family af into binary representation:

>>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4")
b'\x01\x02\x03\x04'

Constant

usocket.AF_INET usocket.AF_INET6

Address family types. Availability depends on the specific MicroPython port.

usocket.SOCK_STREAM usocket.SOCK_DGRAM

The socket type.

usocket.IPPROTO_UDP usocket.IPPROTO_TCP

IP protocol number. Availability depends on the specific MicroPython port. Note that you do not need to specify them when calling usocket.socket(), because SOCK_STREAM socket type will automatically select IPPROTO_TCP and SOCK_DGRAM-IPPROTO_UDP. Therefore, the only practical use of these constants is as a parameter to setsockopt().

usocket.SOL_*

Socket option level (parameter of setsockopt()). The exact inventory depends on the MicroPython port.

usocket.SO_*

Socket options (parameters of setsockopt()). The exact inventory depends on the MicroPython port.

Class socket

Method

socket.close()

Mark that the socket is closed and release all resources. Once this happens, all future operations on the socket object will fail. If the protocol supports it, the remote end will receive the EOF indication.

Sockets are automatically closed when they are garbage collected, but it is recommended that you "close" them immediately after finishing them.

(maixpy ​​not implemented) socket.bind(address)

Bind the socket to the address. The socket must not be bound.

(maixpy ​​not implemented) socket.listen([backlog])

Make the server accept connections. If backlog is specified, it must be at least 0 (if low, set it to 0); and specify the number of unaccepted connections that the system will allow before rejecting new connections. If not specified, the default reasonable value is selected.

(maixpy ​​not implemented) socket.accept()

Accept the connection. The socket must be bound to an address and listen for connections. The return value is a pair (conn, address), where conn is a new socket object that can be used to send and receive data on the connection, and address is the address of the socket bound to the other end of the connection.

socket.connect(address)

Connect to the remote socket at the address.

socket.send(bytes)

Send data to the socket. The socket must be connected to the remote socket. Returns the number of bytes sent, which may be less than the data length ("short write").

socket.sendall(bytes)

Send all data to the socket. The socket must be connected to the remote socket. Unlike send(), this method will try to send all data by continuously sending data blocks.

The behavior of this method on non-blocking sockets is undefined. Therefore, on MicroPython, it is recommended to use the write() method, which has the same "no short write" strategy to block the socket and will return the number of bytes sent on the non-blocking socket.

socket.recv(bufsize)

Receive data from the socket. The return value is a byte object representing the received data. The maximum amount of data received at one time is specified by bufsize.

socket.sendto(bytes, address)

Send data to the socket. The socket should not be connected to the remote socket, because the target socket is specified by the address.

socket.recvfrom(bufsize)

Receive data from the socket. The return value is a pair (byte, address), where bytes is the byte object representing the received data, and address is the address of the socket that sends the data.

socket.setsockopt(level, optname, value)

Set the value of the given socket option. The required symbolic constants are defined in the socket module (SO_* etc.). The value can be an integer or a byte-like object representing a buffer.

socket.settimeout(value)

Note: Not every port supports this method, see below.

Prevent socket operations from setting timeouts. The value parameter can be a non-negative floating point number representing seconds, or it can be None. If a non-zero value is given, if the timeout value has elapsed before the operation is completed, subsequent socket operations will raise an "OSError" exception. If zero is given, the socket is in non-blocking mode. If None is given, the socket is in blocking mode.

Not every "MicroPython port" supports this method. A more portable and universal solution is to use the uselect.poll object. This allows multiple objects to be waited at the same time (not just on sockets, but on generic stream objects that support polling). example:

# Instead of:
s.settimeout(1.0) # time in seconds
s.read(10) # may timeout

# Use:
poller = uselect.poll()
poller.register(s, uselect.POLLIN)
res = poller.poll(1000) # time in milliseconds
if not res:
    # s is still not ready for input, i.e. operation timed out

Difference with CPython

CPython raises socket.timeout exception in case of timeout, which is a subclass of OSError. MicroPython directly raises an OSError. If you use except OSError: to catch exceptions, your code will be valid in both MicroPython and CPython.

socket.setblocking(flag)

Set the blocking or non-blocking mode of the socket: if the flag is false, the socket is set to non-blocking, otherwise it is set to blocking mode.

This method is shorthand for certain settimeout() calls:

sock.setblocking(True) is equivalent to sock.settimeout(None)
sock.setblocking(False) i is equivalent to sock.settimeout(0)

socket.makefile(mode='rb', buffering=0)

Returns the file object associated with the socket. The exact return type depends on the parameters given to makefile(). Support is limited to binary mode ('rb','wb' and'rwb'). CPython parameters: encoding, errors and newlines are not supported.

Difference with CPython

Since MicroPython does not support buffered streams, the value of the buffer parameter is ignored and treated as 0 (unbuffered).

Difference with CPython

Closing the file object returned by makefile() will also close the original socket.

socket.read([size])

Read the size bytes from the slot. Return a bytes object. If no size is given, it will read all the data available in the socket until EOF; therefore, the method will not return until the socket is closed. This function attempts to read the requested data (there is no "short read"). However, for non-blocking sockets, this may not be possible, and then less data will be returned.

socket.readinto(buf[, nbytes])

Read bytes into buf. If nbytes is specified, at most multiple bytes are read. Otherwise, read at most len ​​(buf) bytes. Just like read(), this method follows the "no short read" strategy.

Return value: The number of bytes read and stored in buf.

socket.readline()

Read a line, ending with a newline character.

Return value: the row read.

socket.write(buf)

Write the byte buffer to the socket. This function will try to write all data to the socket (no "short write"). However, for non-blocking sockets, this may not be possible, and the return value will be less than the length of buf.

Return value: The number of bytes written.

exception usocket.error

MicroPython does not have this exception.

Difference with CPython

CPython used to have a socket.error exception and is now deprecated. It is an alias of OSError. In MicroPython, use OSError directly.

Routine

Example 1: Download the picture and display it

Note the need to set WiFi SSID and password

import socket
import network
import gc
import os
import lcd, image

fm.register(board_info.WIFI_RX,fm.fpioa.UART2_TX)
fm.register(board_info.WIFI_TX,fm.fpioa.UART2_RX)
uart = machine.UART(machine.UART.UART2,115200,timeout=1000, read_buf_len=4096)
nic=network.ESP8285(uart)
nic.connect("Sipeed_2.4G","------")

sock = socket.socket()
addr = socket.getaddrinfo("dl.sipeed.com", 80)[0][-1]
sock.connect(addr)
sock.send('''GET /MAIX/MaixPy/assets/Alice.bmp HTTP/1.1
Host: dl.sipeed.com
cache-control: no-cache

''')

img = b""
sock.settimeout(5)
while True:
    data = sock.recv(4096)
    if len(data) == 0:
        break
    print("rcv:", len(data))
    img = img + data

print(len(img))
img = img[img.find(b"\r\n\r\n")+4:]
print(len(img))
print("save to /sd/Alice.bmp")
f = open("/sd/Alice.bmp","wb")
f.write(img)
f.close()
print("save ok")
print("display")
img = image.Image("/sd/Alice.bmp")
lcd.init()
lcd.display(img)

Example 2: Sending pictures


import os
import socket
import network
import gc

fm.register(board_info.WIFI_RX,fm.fpioa.UART2_TX)
fm.register(board_info.WIFI_TX,fm.fpioa.UART2_RX)
uart = machine.UART(machine.UART.UART2,115200,timeout=1000, read_buf_len=4096)
nic=network.ESP8285(uart)
nic.connect("Sipeed_2.4G","-------")

addr = ("192.168.0.183", 3456)
sock = socket.socket()
sock.connect(addr)
sock.settimeout(5)

f = open("/sd/Alice.bmp","rb")
while True:
    img = f.read(2048)
    if not img or (len(img) == 0):
        break
    sock.send(img)
f.close()
sock.close()