socket – 插座模块

该模块实现了相应 CPython 模块的 一个子集,如下所述。有关更多信息,请参阅原始 CPython 文档: socket.

该模块提供对 BSD 套接字接口的访问。

与 CPython 的区别

为了效率和一致性,MicroPython 中的套接字对象直接实现了 stream (类文件)接口。在 CPython 中,您需要使用makefile()方法将套接字转换为类文件对象。MicroPython 仍支持此方法(但不可操作),因此在与 CPython 的兼容性很重要的情况下,请务必使用它。

套接字地址格式

socket 模块的原生socket地址格式是getaddrinfo函数返回的不透明数据类型,必须用于解析文本地址(包括数字地址):

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

使用 getaddrinfo是处理地址的最有效(在内存和处理能力方面)和可移植的方式。

但是,socket模块(注意与socket此处描述的本机 MicroPython模块的区别 )提供了与 CPython 兼容的方式来使用元组指定地址,如下所述。请注意,根据MicroPython 端口, socket模块可以内置或需要安装 micropython-lib(如 MicroPython Unix 端口的情况),并且一些端口仍然只接受元组格式的数字地址,并且需要使用getaddrinfo 函数来解析域名称。

加起来:

  • getaddrinfo在编写便携式应用程序时始终使用。

  • 如果您的端口支持,下面描述的元组地址可以用作快速黑客和交互使用的快捷方式。

socket模块的元组地址格式:

  • IPv4: (ipv4_address, port),其中ipv4_address是一个带有点符号数字 IPv4 地址的字符串,例如 "8.8.8.8",并且port是 1-65535 范围内的整数端口号。注意域名不被接受为ipv4_address,它们应该首先使用socket.getaddrinfo().

  • IPv6: (ipv6_address, port, flowinfo, scopeid),其中ipv6_address 是带有冒号符号的数字 IPv6 地址的字符串,例如"2001:db8::1",而port是 1-65535 范围内的整数端口号。flowinfo 必须为0。scopeid是链路本地地址的接口范围标识符。注意域名不被接受为ipv6_address,它们应该首先使用 socket.getaddrinfo(). IPv6 支持的可用性取决于 MicroPython 端口

职能

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

使用给定的地址族、套接字类型和协议号创建一个新套接字。请注意,在大多数情况下不需要指定proto(并且不推荐,因为某些 MicroPython 端口可能会省略IPPROTO_*常量)。相反,类型参数将自动选择所需的协议:

# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
socket.getaddrinfo(host, port, af=0, type=0, proto=0, flags=0, /)

将主机/端口参数转换为 5 元组序列,其中包含创建连接到该服务的套接字所需的所有参数。参数 af、type和proto(其含义与socket() 函数相同)可用于过滤返回的地址类型。如果没有指定参数或参数为零,则可以返回所有地址组合(需要用户侧过滤)。

生成的 5 元组列表具有以下结构:

(family, type, proto, canonname, sockaddr)

以下示例显示了如何连接到给定的 url:

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

过滤参数的推荐使用:

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

与 CPython 的区别

如果此函数出错,CPython 会引发socket.gaierror 异常(OSError子类)。MicroPython 没有socket.gaierror 并直接引发 OSError。请注意,错误编号 getaddrinfo()形成一个单独的命名空间,可能与 errno模块中的错误编号不匹配。为了区分getaddrinfo()错误,它们用负数表示,而标准系统错误是正数(错误号可以使用e.args[0]异常对象的属性访问)。负值的使用是一个临时细节,将来可能会改变。

socket.inet_ntop(af, bin_addr)

将给定地址族af的二进制网络地址bin_addr转换为 文本表示:

>>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'
socket.inet_pton(af, txt_addr)

将给定地址族af的文本网络地址txt_addr转换为 二进制表示:

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

常数

socket.AF_INET
socket.AF_INET6

地址族类型。可用性取决于特定的MicroPython 端口

socket.SOCK_STREAM
socket.SOCK_DGRAM

套接字类型。

socket.IPPROTO_UDP
socket.IPPROTO_TCP

IP 协议编号。可用性取决于特定的MicroPython 端口。请注意,您不需要在对 的调用中指定这些socket.socket(),因为 SOCK_STREAM 套接字类型会自动选择IPPROTO_TCPSOCK_DGRAM - IPPROTO_UDP。因此,这些常量的唯一真正用途是作为 的参数 setsockopt()

socket.SOL_*

套接字选项级别( 的参数setsockopt())。确切的清单取决于MicroPython 端口

socket.SO_*

套接字选项( 的参数setsockopt())。确切的清单取决于MicroPython 端口

特定于 WiPy 的常量:

socket.IPPROTO_SEC

用于创建 SSL 兼容套接字的特殊协议值。

类套接字

方法

socket.close()

将套接字标记为关闭并释放所有资源。一旦发生这种情况,套接字对象上的所有未来操作都将失败。如果协议支持,对端将收到 EOF 指示。

套接字在被垃圾收集时会自动关闭,但建议close() 您在完成对它们的使用后立即向它们明确推荐。

socket.bind(address)

将套接字绑定到address。套接字必须尚未绑定。

socket.listen([backlog])

启用服务器以接受连接。如果指定backlog,则必须至少为0(如果较低,则设置为0);并指定系统在拒绝新连接之前允许的未接受连接数。如果未指定,则选择默认的合理值。

socket.accept()

接受连接。套接字必须绑定到一个地址并侦听连接。返回值是一对 (conn, address),其中 conn 是可用于在连接上发送和接收数据的新套接字对象,address 是绑定到连接另一端的套接字的地址。

socket.connect(address)

连接到地址为的远程套接字。

socket.send(bytes)

向套接字发送数据。套接字必须连接到远程套接字。返回发送的字节数,可能小于数据长度(“短写”)。

socket.sendall(bytes)

将所有数据发送到套接字。套接字必须连接到远程套接字。与 不同send(),此方法将尝试通过连续发送数据块来发送所有数据。

此方法在非阻塞套接字上的行为未定义。因此,在 MicroPython 上,建议使用write()method 代替,它具有相同的“无短写”策略用于阻塞套接字,并将返回在非阻塞套接字上发送的字节数。

socket.recv(bufsize)

从套接字接收数据。返回值是一个字节对象,表示接收到的数据。一次接收的最大数据量由 bufsize 指定。

socket.sendto(bytes, address)

向套接字发送数据。套接字不应连接到远程套接字,因为目标套接字由address指定。

socket.recvfrom(bufsize)

从套接字接收数据。返回值是一对(字节,地址),其中字节是表示接收到的数据的字节对象,地址是发送数据的套接字的地址。

socket.setsockopt(level, optname, value)

设置给定套接字选项的值。所需的符号常量在套接字模块(SO_* 等)中定义。该值可以是表示缓冲区的整数或类似字节的对象。

socket.settimeout(value)

注意: 并非每个端口都支持此方法,请参见下文。

设置阻塞套接字操作的超时时间。value 参数可以是表示秒的非负浮点数,也可以是 None。如果给出了一个非零值,OSError如果超时时间值在操作完成之前已经过去,则后续的套接字操作将引发异常。如果给出零,则套接字处于非阻塞模式。如果给出 None ,则套接字处于阻塞模式。

并非每个 MicroPython 端口都支持这种方法。一个更便携和通用的解决方案是使用 select.poll object. 这允许同时等待多个对象(不仅在套接字上,而且在stream 支持轮询的通用 对象上)。例子:

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

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

与 CPython 的区别

CPythonsocket.timeout 在超时的情况下引发异常,这是一个 OSError 子类。MicroPython 会直接引发 OSError。如果您使用捕获异常,您的代码将在 MicroPython 和 CPython 中工作。except OSError:

socket.setblocking(flag)

设置socket的阻塞或非阻塞模式:如果flag为false,则socket设置为非阻塞模式,否则设置为阻塞模式。

此方法是某些settimeout() 调用的简写:

  • sock.setblocking(True)相当于 sock.settimeout(None)

  • sock.setblocking(False) 相当于sock.settimeout(0)

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

返回与套接字关联的文件对象。确切的返回类型取决于提供给 makefile() 的参数。支持仅限于二进制模式('rb'、'wb' 和 'rwb')。不支持CPython 的参数:encoding、errors和newline。

与 CPython 的区别

由于 MicroPython 不支持缓冲流,缓冲 参数的值将被忽略并视为 0(未缓冲)。

与 CPython 的区别

关闭由 makefile() 返回的文件对象也将关闭原始套接字。

socket.read([size])

从套接字读取最多 size 个字节。返回一个字节对象。如果未指定大小,则从套接字读取所有可用数据,直到 EOF;因此,该方法在套接字关闭之前不会返回。该函数尝试读取尽可能多的数据(没有“短读”)。但是,对于非阻塞套接字,这可能是不可能的,然后将返回较少的数据。

socket.readinto(buf[, nbytes])

将字节读入buf。如果指定了nbytes,则最多读取那么多字节。否则,最多读取len(buf)个字节。就像 read(),这种方法遵循“无短读”政策。

返回值:读取并存储到buf 中的字节数。

socket.readline()

读取一行,以换行符结尾。

返回值:读取的行。

socket.write(buf)

将字节缓冲区写入套接字。此函数将尝试将所有数据写入套接字(无“短写”)。但是对于非阻塞套接字,这可能是不可能的,并且返回值将小于buf的长度。

返回值:写入的字节数。

exception socket.error

MicroPython 没有这个例外。

与 CPython 的区别

CPython 曾经有一个socket.error 异常,现在已弃用,它是 OSError. 在MicroPython中,OSError 直接使用。