Skip to main content

18.1. socket —低级网络接口

源代码: Lib/socket.py


此模块提供对BSD socket 接口的访问。它可用于所有现代的Unix系统,Windows,MacOS和可能的附加平台。

注解

某些行为可能依赖于平台,因为调用操作系统套接字API。

Python接口是Unix系统调用和套接字的库接口到Python的面向对象样式的直接音译:socket() 函数返回一个 socket object,它的方法实现各种套接字系统调用。参数类型比C接口中的高一些:与Python文件上的 read()write() 操作一样,接收操作上的缓冲区分配是自动的,缓冲区长度对发送操作是隐含的。

参见

模块 socketserver

简化编写网络服务器的类。

模块 ssl

套接字对象的TLS/SSL包装器。

18.1.1. 插座系列

根据系统和构建选项,此模块支持各种插座系列。

根据创建套接字对象时指定的地址系列,自动选择特定套接字对象所需的地址格式。套接字地址表示如下:

  • 使用文件系统编码和 'surrogateescape' 错误处理程序(请参阅 PEP 383)将绑定到文件系统节点的 AF_UNIX 套接字的地址表示为字符串。 Linux抽象命名空间中的地址返回为具有初始空字节的 bytes-like object;请注意,此命名空间中的套接字可以与正常的文件系统套接字通信,因此要在Linux上运行的程序可能需要处理这两种类型的地址。字符串或类似字节的对象可以用作任何类型的地址作为参数传递。

    在 3.3 版更改: 以前,假设 AF_UNIX 套接字路径使用UTF-8编码。

    在 3.5 版更改: 可写 bytes-like object 现已被接受。

  • A对 (host, port) 用于 AF_INET 地址族,其中 host 是表示诸如 'daring.cwi.nl' 的因特网域标记中的主机名或者诸如 '100.50.200.5' 的IPv4地址的字符串,并且 port 是整数。

  • 对于 AF_INET6 地址族,使用四元组 (host, port, flowinfo, scopeid),其中 flowinfoscopeid 表示 struct sockaddr_in6 中的 sin6_flowinfosin6_scope_id 成员。对于 socket 模块方法,为了向后兼容性,可以省略 flowinfoscopeid。但是,请注意,省略 scopeid 可能会导致操作范围内的IPv6地址时出现问题。

  • AF_NETLINK 套接字表示为对 (pid, groups)

  • 仅使用 AF_TIPC 地址系列支持仅使用Linux的TIPC。 TIPC是一种开放的,基于非IP的网络协议,设计用于集群计算机环境。地址由元组表示,并且字段取决于地址类型。一般元组形式是 (addr_type, v1, v2, v3 [, scope]),其中:

    • addr_typeTIPC_ADDR_NAMESEQTIPC_ADDR_NAMETIPC_ADDR_ID 之一。

    • scopeTIPC_ZONE_SCOPETIPC_CLUSTER_SCOPETIPC_NODE_SCOPE 中的一种。

    • 如果 addr_typeTIPC_ADDR_NAME,则 v1 是服务器类型,v2 是端口标识符,并且 v3 应该是0。

      如果 addr_typeTIPC_ADDR_NAMESEQ,则 v1 是服务器类型,v2 是较低的端口号,而 v3 是较高的端口号。

      如果 addr_typeTIPC_ADDR_ID,则 v1 是节点,v2 是参考,并且 v3 应该被设置为0。

  • 元组 (interface, ) 用于 AF_CAN 地址族,其中 interface 是表示网络接口名称(如 'can0')的字符串。网络接口名称 '' 可用于接收来自该系列的所有网络接口的数据包。

  • 字符串或元组 (id, unit) 用于 PF_SYSTEM 族的 SYSPROTO_CONTROL 协议。该字符串是使用动态分配的ID的内核控件的名称。如果内核控制的ID和单元号已知或者如果使用注册的ID,则可以使用元组。

    3.3 新版功能.

  • AF_BLUETOOTH 支持以下协议和地址格式:

    • BTPROTO_L2CAP 接受 (bdaddr, psm),其中 bdaddr 是蓝牙地址作为字符串,psm 是整数。

    • BTPROTO_RFCOMM 接受 (bdaddr, channel),其中 bdaddr 是蓝牙地址作为字符串,channel 是整数。

    • BTPROTO_HCI 接受 (device_id,),其中 device_id 是带有接口的蓝牙地址的整数或字符串。 (这取决于你的操作系统; NetBSD和DragonFlyBSD期望一个蓝牙地址,而一切都期望一个整数)。

      在 3.2 版更改: 已添加NetBSD和DragonFlyBSD支持。

    • BTPROTO_SCO 接受 bdaddr,其中 bdaddr 是包含字符串格式的蓝牙地址的 bytes 对象。 (ex。b'12:23:34:45:56:67')FreeBSD不支持此协议。

  • AF_ALG 是基于Linux的基于套接字的内核加密接口。算法套接字配置有2到4个元素 (type, name [, feat [, mask]]) 的元组,其中:

    • type 是字符串的算法类型,例如。 aeadhashskcipherrng

    • name 是算法名称和操作模式作为字符串,例如。 sha256hmac(sha256)cbc(aes)drbg_nopr_ctr_aes256

    • featmask 是无符号32位整数。

    可用性Linux 2.6.38,一些算法类型需要更多最近的内核。

    3.6 新版功能.

  • 某些其他地址系列(AF_PACKETAF_CAN)支持特定表示。

对于IPv4地址,接受两种特殊格式而不是主机地址:空字符串表示 INADDR_ANY,字符串 '<broadcast>' 表示 INADDR_BROADCAST。此行为与IPv6不兼容,因此,如果您打算使用Python程序支持IPv6,则可能希望避免这些行为。

如果在IPv4/v6套接字地址的 host 部分中使用主机名,则程序可能显示不确定的行为,因为Python使用从DNS解析返回的第一个地址。根据DNS解析和/或主机配置的结果,套接字地址将被不同地解析为实际的IPv4/v6地址。对于确定性行为,在 host 部分中使用数字地址。

所有错误引发异常。可以提出无效参数类型和内存不足条件的正常异常;从Python 3.3开始,与套接字或地址语义相关的错误引发 OSError 或其中一个子类(它们用于提高 socket.error)。

通过 setblocking() 支持非阻塞模式。基于超时的这种概括通过 settimeout() 来支持。

18.1.2. 模块内容

模块 socket 导出以下元素。

18.1.2.1. 例外

exception socket.error

OSError 的已弃用别名。

在 3.3 版更改: PEP 3151 之后,这个类被作为 OSError 的别名。

exception socket.herror

作为 OSError 的子类,针对地址相关错误,即对于在POSIX C API中使用 h_errno 的函数(包括 gethostbyname_ex()gethostbyaddr()),引发此异常。附带的值是一个 (h_errno, string) 对,表示库调用返回的错误。 h_errno 是一个数值,而 string 表示由 hstrerror() C函数返回的 h_errno 的描述。

在 3.3 版更改: 这个类是 OSError 的子类。

exception socket.gaierror

作为 OSError 的子类,通过 getaddrinfo()getnameinfo() 引发与地址相关的错误的异常。附带的值是一个 (error, string) 对,表示库调用返回的错误。 string 表示由 gai_strerror() C函数返回的 error 的描述。数字 error 值将匹配此模块中定义的一个 EAI_* 常量。

在 3.3 版更改: 这个类是 OSError 的子类。

exception socket.timeout

作为 OSError 的子类,当在通过事先调用 settimeout() (或隐含地通过 setdefaulttimeout())启用了超时的套接字上发生超时时,引发此异常。附带的值是一个字符串,其值当前总是“超时”。

在 3.3 版更改: 这个类是 OSError 的子类。

18.1.2.2. 常量

AF_* 和 SOCK_* 常数现在是 AddressFamilySocketKind IntEnum 集合。

3.4 新版功能.

socket.AF_UNIX
socket.AF_INET
socket.AF_INET6

这些常量表示地址(和协议)系列,用于 socket() 的第一个参数。如果未定义 AF_UNIX 常数,则不支持此协议。根据系统的不同,可能有更多的常数可用。

socket.SOCK_STREAM
socket.SOCK_DGRAM
socket.SOCK_RAW
socket.SOCK_RDM
socket.SOCK_SEQPACKET

这些常量表示套接字类型,用于 socket() 的第二个参数。根据系统的不同,可能有更多的常数可用。 (只有 SOCK_STREAMSOCK_DGRAM 似乎通常有用。)

socket.SOCK_CLOEXEC
socket.SOCK_NONBLOCK

这两个常量,如果定义,可以与套接字类型组合,并允许您设置一些标志原子(从而避免可能的竞争条件和需要单独的调用)。

参见

安全文件描述符处理 进行更详细的解释。

可用性:Linux> = 2.6.27。

3.2 新版功能.

SO_*
socket.SOMAXCONN
MSG_*
SOL_*
SCM_*
IPPROTO_*
IPPORT_*
INADDR_*
IP_*
IPV6_*
EAI_*
AI_*
NI_*
TCP_*

在套接字模块中还定义了这些形式的许多常量,这些常量在Unix文档中有关套接字和/或IP协议。它们通常用于套接字对象的 setsockopt()getsockopt() 方法的参数。在大多数情况下,只定义在Unix头文件中定义的那些符号;对于几个符号,提供默认值。

在 3.6 版更改: SO_DOMAINSO_PROTOCOLSO_PEERSECSO_PASSSEC

socket.AF_CAN
socket.PF_CAN
SOL_CAN_*
CAN_*

Linux文档中记录的这些形式的许多常量也在套接字模块中定义。

可用性:Linux> = 2.6.25。

3.3 新版功能.

socket.CAN_BCM
CAN_BCM_*

CAN_BCM在CAN协议族中是广播管理器(BCM)协议。在Linux文档中记录的广播管理器常量也在套接字模块中定义。

可用性:Linux> = 2.6.25。

3.4 新版功能.

socket.CAN_RAW_FD_FRAMES

在CAN_RAW插座中启用CAN FD支持。默认情况下禁用。这允许您的应用程序发送CAN和CAN FD帧;但是,从插座读取时,您必须接受CAN和CAN FD帧。

这个常量在Linux文档中有记录。

可用性:Linux> = 3.6。

3.5 新版功能.

socket.AF_RDS
socket.PF_RDS
socket.SOL_RDS
RDS_*

Linux文档中记录的这些形式的许多常量也在套接字模块中定义。

可用性:Linux> = 2.6.30。

3.3 新版功能.

socket.SIO_RCVALL
socket.SIO_KEEPALIVE_VALS
socket.SIO_LOOPBACK_FAST_PATH
RCVALL_*

Windows的WSAIoctl()的常量。常量用作套接字对象的 ioctl() 方法的参数。

在 3.6 版更改: 加入 SIO_LOOPBACK_FAST_PATH

TIPC_*

TIPC相关常量,匹配由C套接字API导出的常量。有关详细信息,请参阅TIPC文档。

socket.AF_ALG
socket.SOL_ALG
ALG_*

Linux内核加密的常数。

可用性:Linux> = 2.6.38。

3.6 新版功能.

可用性:BSD,OSX。

3.4 新版功能.

socket.has_ipv6

此常量包含一个布尔值,指示此平台是否支持IPv6。

socket.BDADDR_ANY
socket.BDADDR_LOCAL

这些是包含具有特殊含义的蓝牙地址的字符串常量。例如,当使用 BTPROTO_RFCOMM 指定绑定套接字时,BDADDR_ANY 可用于指示任何地址。

socket.HCI_FILTER
socket.HCI_TIME_STAMP
socket.HCI_DATA_DIR

用于 BTPROTO_HCIHCI_FILTER 不适用于NetBSD或DragonFlyBSD。 HCI_TIME_STAMPHCI_DATA_DIR 不适用于FreeBSD,NetBSD或DragonFlyBSD。

18.1.2.3. 功能

18.1.2.3.1. 创建套接字

以下功能都创建 套接字对象

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

使用给定的地址族,套接字类型和协议号创建一个新的套接字。地址系列应为 AF_INET (默认),AF_INET6AF_UNIXAF_CANAF_RDS。套接字类型应该是 SOCK_STREAM (默认),SOCK_DGRAMSOCK_RAW 或者可能是其他 SOCK_ 常量之一。协议号通常为零,可以省略,或者在地址族是 AF_CAN 的情况下,协议应该是 CAN_RAWCAN_BCM 中的一个。如果指定了 fileno,则忽略其他参数,导致具有指定文件描述符的套接字返回。与 socket.fromfd() 不同,fileno 将返回相同的套接字,而不是重复。这可能有助于使用 socket.close() 关闭分离的套接字。

新创建的套接字是 不可继承

在 3.3 版更改: 添加了AF_CAN系列。 AF_RDS系列已添加。

在 3.4 版更改: 添加了CAN_BCM协议。

在 3.4 版更改: 返回的套接字现在是不可继承的。

socket.socketpair([family[, type[, proto]]])

使用给定的地址族,套接字类型和协议号构建一对连接的套接字对象。地址系列,插座类型和协议号与上述 socket() 功能相同。如果在平台上定义,默认族是 AF_UNIX;否则,默认为 AF_INET

新创建的套接字是 不可继承

在 3.2 版更改: 返回的套接字对象现在支持整个套接字API,而不是一个子集。

在 3.4 版更改: 返回的套接字现在是不可继承的。

在 3.5 版更改: 添加Windows支持。

socket.create_connection(address[, timeout[, source_address]])

连接到侦听Internet address (2元组 (host, port))的TCP服务,并返回套接字对象。这是比 socket.connect() 更高级的函数:如果 host 是非数字主机名,它将尝试为 AF_INETAF_INET6 解析它,然后尝试连接到所有可能的地址,直到连接成功。这使得编写与IPv4和IPv6兼容的客户端变得容易。

传递可选的 timeout 参数将在尝试连接之前设置套接字实例上的超时。如果未提供 timeout,则使用 getdefaulttimeout() 返回的全局默认超时设置。

如果提供,source_address 必须是2元组 (host, port),套接字绑定为其源地址,然后连接。如果主机或端口分别为“0”或0,将使用操作系统默认行为。

在 3.2 版更改: 加入 source_address

socket.fromfd(fd, family, type, proto=0)

复制文件描述符 fd (由文件对象的 fileno() 方法返回的整数),并从结果中构建一个套接字对象。地址系列,插座类型和协议号与上述 socket() 功能相同。文件描述符应该引用套接字,但这不是被检查—如果文件描述符无效,对象上的后续操作可能会失败。此函数很少需要,但可用于获取或设置作为标准输入或输出传递给程序的套接字选项(例如由Unix inet守护程序启动的服务器)。假定套接字处于阻塞模式。

新创建的套接字是 不可继承

在 3.4 版更改: 返回的套接字现在是不可继承的。

socket.fromshare(data)

socket.share() 方法获得的数据实例化套接字。假定套接字处于阻塞模式。

可用性:Windows。

3.3 新版功能.

socket.SocketType

这是一个表示套接字对象类型的Python类型对象。它与 type(socket(...)) 相同。

18.1.2.3.2. 其他功能

socket 模块还提供各种网络相关服务:

socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0)

host/port 参数转换为包含创建连接到该服务的套接字所需的所有参数的5元组序列。 host 是域名,IPv4/v6地址或 None 的字符串表示形式。 port 是字符串服务名称,例如 'http',数字端口号或 None。通过传递 None 作为 hostport 的值,您可以将 NULL 传递给底层C API。

可以可选地指定 familytypeproto 参数,以便缩小返回的地址列表。将零作为这些参数中的每一个的值传递,选择完整范围的结果。 flags 参数可以是一个或多个 AI_* 常量,并且将影响如何计算和返回结果。例如,AI_NUMERICHOST 将禁用域名解析,如果 host 是域名,将会引发错误。

该函数返回具有以下结构的5元组列表:

(family, type, proto, canonname, sockaddr)

在这些元组中,familytypeproto 都是整数,并且意在传递给 socket() 函数。如果 AI_CANONNAMEflags 参数的一部分,则 canonname 将是表示 host 的规范名称的字符串;否则 canonname 将为空。 sockaddr 是描述套接字地址的元组,其格式取决于返回的 familyAF_INET(address, port) 2元组,AF_INET6(address, port, flow info, scope id) 4元组),并且意在传递给 socket.connect() 方法。

以下示例获取到端口80上 example.org 的假设TCP连接的地址信息(如果未启用IPv6,则系统上的结果可能不同):

>>> socket.getaddrinfo("example.org", 80, proto=socket.IPPROTO_TCP)
[(<AddressFamily.AF_INET6: 10>, <SocketType.SOCK_STREAM: 1>,
 6, '', ('2606:2800:220:1:248:1893:25c8:1946', 80, 0, 0)),
 (<AddressFamily.AF_INET: 2>, <SocketType.SOCK_STREAM: 1>,
 6, '', ('93.184.216.34', 80))]

在 3.2 版更改: 参数现在可以使用关键字参数传递。

socket.getfqdn([name])

返回 name 的完全限定域名。如果 name 被省略或为空,它将被解释为本地主机。要查找完全限定名,将检查 gethostbyaddr() 返回的主机名,后面是主机的别名(如果可用)。选择包含句点的名字。如果没有完全限定域名可用,则返回 gethostname() 返回的主机名。

socket.gethostbyname(hostname)

将主机名转换为IPv4地址格式。 IPv4地址作为字符串返回,例如 '100.50.200.5'。如果主机名是IPv4地址本身,则返回不变。有关更完整的界面,请参阅 gethostbyname_ex()gethostbyname() 不支持IPv6名称解析,并且应该使用 getaddrinfo() 作为IPv4/v6双协议栈的支持。

socket.gethostbyname_ex(hostname)

将主机名转换为IPv4地址格式,扩展接口。返回三个 (hostname, aliaslist, ipaddrlist),其中 hostname 是响应给定 ip_address 的主要主机名,aliaslist 是相同地址的替代主机名的列表(可能为空),ipaddrlist 是同一主机上相同接口的IPv4地址列表(通常但不总是单个地址)。 gethostbyname_ex() 不支持IPv6名称解析,应该使用 getaddrinfo() 代替IPv4/v6双栈支持。

socket.gethostname()

返回一个包含Python解释器当前正在执行的机器的主机名的字符串。

注意:gethostname() 不总是返回完全限定的域名;使用 getfqdn()

socket.gethostbyaddr(ip_address)

返回三个 (hostname, aliaslist, ipaddrlist),其中 hostname 是响应给定 ip_address 的主要主机名,aliaslist 是相同地址的可选主机名的列表(可能为空),ipaddrlist 是同一接口的IPv4/v6地址列表相同的主机(很可能只包含一个地址)。要查找完全限定域名,请使用函数 getfqdn()gethostbyaddr() 支持IPv4和IPv6。

socket.getnameinfo(sockaddr, flags)

将套接字地址 sockaddr 转换为2元组 (host, port)。根据 flags 的设置,结果可以包含 host 中的完全限定域名或数字地址表示。类似地,port 可以包含字符串端口名或数字端口号。

socket.getprotobyname(protocolname)

将Internet协议名称(例如,'icmp')转换为适合作为(可选)第三个参数传递给 socket() 函数的常量。这通常只需要在“原始”模式(SOCK_RAW)中打开的插座;对于正常的套接字模式,如果协议被省略或零,则自动选择正确的协议。

socket.getservbyname(servicename[, protocolname])

将Internet服务名称和协议名称转换为该服务的端口号。可选的协议名称,如果给出,应该是 'tcp''udp',否则任何协议将匹配。

socket.getservbyport(port[, protocolname])

将Internet端口号和协议名称转换为该服务的服务名称。可选的协议名称,如果给出,应该是 'tcp''udp',否则任何协议将匹配。

socket.ntohl(x)

将32位正整数从网络转换为主机字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是一个无操作;否则,它执行4字节交换操作。

socket.ntohs(x)

将16位正整数从网络转换为主机字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是一个无操作;否则,它执行2字节交换操作。

socket.htonl(x)

将32位正整数从主机转换为网络字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是一个无操作;否则,它执行4字节交换操作。

socket.htons(x)

将16位正整数从主机转换为网络字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是一个无操作;否则,它执行2字节交换操作。

socket.inet_aton(ip_string)

将IPv4地址从点分四元字符串格式(例如,“123.45.67.89”)转换为32位打包二进制格式,长度为四个字符的字节对象。当与使用标准C库并且需要 struct in_addr 类型的对象(这是该函数返回的32位打包二进制的C类型)进行交谈时,这是非常有用的。

inet_aton() 也接受少于三个点的字符串;有关详细信息,请参阅Unix手册页 inet(3)

如果传递给此函数的IPv4地址字符串无效,则将引发 OSError。注意,什么是有效的取决于 inet_aton() 的底层C实现。

inet_aton() 不支持IPv6,inet_pton() 应该用于IPv4/v6双协议栈支持。

socket.inet_ntoa(packed_ip)

将32位打包IPv4地址(长度为四个字节的 bytes-like object)转换为其标准点分四元组字符串表示形式(例如,“123.45.67.89”)。当与使用标准C库并需要类型 struct in_addr 的对象(这是此函数作为参数的32位打包二进制数据的C类型)进行交谈时,这是非常有用的。

如果传递给此函数的字节序列的长度不完全是4个字节,则 OSError 将被引发。 inet_ntoa() 不支持IPv6,inet_ntop() 应该用于IPv4/v6双协议栈支持。

在 3.5 版更改: 可写 bytes-like object 现已被接受。

socket.inet_pton(address_family, ip_string)

将IP地址从其特定于家庭的字符串格式转换为压缩的二进制格式。当库或网络协议要求类型为 struct in_addr (类似于 inet_aton())或 struct in6_addr 的对象时,inet_pton() 是有用的。

address_family 的支持值目前为 AF_INETAF_INET6。如果IP地址字符串 ip_string 无效,则会引发 OSError。注意,什么是有效的取决于 address_family 的值和 inet_pton() 的基本实现。

可用性:Unix(可能不是所有平台),Windows。

在 3.4 版更改: 添加Windows支持

socket.inet_ntop(address_family, packed_ip)

将打包的IP地址(某些字节数的 bytes-like object)转换为其标准的特定于家族的字符串表示形式(例如 '7.10.0.5''5aef:2b::8')。 inet_ntop() 在库或网络协议返回类型 struct in_addr (类似于 inet_ntoa())或 struct in6_addr 的对象时很有用。

address_family 的支持值目前为 AF_INETAF_INET6。如果字节对象 packed_ip 不是指定地址族的正确长度,则将引发 ValueErrorOSError 针对来自对 inet_ntop() 的调用的错误而引发。

可用性:Unix(可能不是所有平台),Windows。

在 3.4 版更改: 添加Windows支持

在 3.5 版更改: 可写 bytes-like object 现已被接受。

socket.CMSG_LEN(length)

返回具有给定 length 的相关数据的辅助数据项的总长度,而无后端填充。此值通常可用作 recvmsg() 的缓冲区大小以接收单个辅助数据项,但是 RFC 3542 要求便携式应用程序使用 CMSG_SPACE(),因此包括用于填充的空间,即使项目将是缓冲区中的最后一个。如果 length 超出允许的值范围,则提高 OverflowError

可用性:大多数Unix平台,可能是其他平台。

3.3 新版功能.

socket.CMSG_SPACE(length)

返回 recvmsg() 接收具有给定 length 的相关数据的辅助数据项所需的缓冲区大小,以及任何尾部填充。接收多个项所需的缓冲区空间是其相关数据长度的 CMSG_SPACE() 值的总和。如果 length 超出允许的值范围,则提高 OverflowError

注意,一些系统可能支持辅助数据而不提供此功能。另请注意,使用此函数的结果设置缓冲区大小可能不会精确限制可接收的辅助数据量,因为附加数据可能能够适应填充区域。

可用性:大多数Unix平台,可能是其他平台。

3.3 新版功能.

socket.getdefaulttimeout()

返回新套接字对象的默认超时(以秒为单位)(float)。 None 的值表示新的套接字对象没有超时。首次导入插槽模块时,默认值为 None

socket.setdefaulttimeout(timeout)

设置新的socket对象以秒为单位(浮点)的默认超时。当插座模块被首次导入,则默认为 None。见 settimeout() 的可能值和它们各自的含义。

socket.sethostname(name)

将机器的主机名设置为 name。如果你没有足够的权利,这将提高 OSError

可用性:Unix。

3.3 新版功能.

socket.if_nameindex()

返回网络接口信息(索引int,名称字符串)元组的列表。 OSError 如果系统调用失败。

可用性:Unix。

3.3 新版功能.

socket.if_nametoindex(if_name)

返回与接口名称对应的网络接口索引号。 OSError,如果没有给定名称的接口存在。

可用性:Unix。

3.3 新版功能.

socket.if_indextoname(if_index)

返回与接口索引号相对应的网络接口名称。 OSError,如果没有给定索引的接口存在。

可用性:Unix。

3.3 新版功能.

18.1.3. 套接字对象

Socket对象有以下方法。除了 makefile(),这些对应于适用于套接字的Unix系统调用。

在 3.2 版更改: 增加了对 context manager 协议的支持。退出上下文管理器相当于调用 close()

socket.accept()

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

新创建的套接字是 不可继承

在 3.4 版更改: 套接字现在是不可继承的。

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.bind(address)

将套接字绑定到 address。套接字不必已绑定。 (address 的格式取决于地址系列 - 见上文)。

socket.close()

标记套接字关闭。当来自 makefile() 的所有文件对象被关闭时,底层系统资源(例如文件描述符)也被关闭。一旦发生这种情况,对套接字对象的所有未来操作都将失败。远程端将不再接收数据(在排队的数据被刷新之后)。

套接字在被垃圾收集时自动关闭,但建议明确地对它们进行 close(),或者在它们周围使用 with 语句。

在 3.6 版更改: 如果发生基础 close() 调用时发生错误,则 OSError 现在升高。

注解

close() 释放与连接相关联的资源,但不一定立即关闭连接。如果要及时关闭连接,请在 close() 之前调用 shutdown()

socket.connect(address)

连接到 address 上的远程插座。 (address 的格式取决于地址系列 - 见上文)。

如果连接被信号中断,则该方法将等待直到连接完成,或者如果信号处理程序不引发异常并且套接字正在阻塞或已超时,则在超时时引发 socket.timeout。对于非阻塞套接字,如果连接被信号(或由信号处理程序引发的异常)中断,该方法将引发 InterruptedError 异常。

在 3.5 版更改: 该方法现在等待直到连接完成,而不是如果连接被信号中断,信号处理程序不引发异常并且套接字正在阻塞或有超时,则提高 InterruptedError 异常(参见 PEP 475 的原理)。

socket.connect_ex(address)

connect(address),但返回一个错误指示器,而不是为C级 connect() 调用返回的错误提出异常(其他问题,如“未找到主机”,仍然可能引发异常)。如果操作成功,错误指示符为 0,否则为 errno 变量的值。这对于支持例如异步连接是有用的。

socket.detach()

将套接字对象置于关闭状态,而不实际关闭底层文件描述符。返回文件描述符,并且可以重用于其他目的。

3.2 新版功能.

socket.dup()

复制套接字。

新创建的套接字是 不可继承

在 3.4 版更改: 套接字现在是不可继承的。

socket.fileno()

返回套接字文件描述符(一个小整数),或者失败时返回-1。这对 select.select() 很有用。

在Windows下,此方法返回的小整数不能用于可以使用文件描述符的地方(如 os.fdopen())。 Unix没有这个限制。

socket.get_inheritable()

获取套接字文件描述符或套接字句柄的 继承标志True 如果套接字可以在子进程中继承,则 False 如果不能。

3.4 新版功能.

socket.getpeername()

返回套接字连接的远程地址。例如,这有助于找出远程IPv4/v6套接字的端口号。 (返回的地址格式取决于地址系列—见上文。)在某些系统上,不支持此功能。

socket.getsockname()

返回套接字自己的地址。这有助于找出例如IPv4/v6套接字的端口号。 (返回的地址格式取决于地址族 - 见上文。)

socket.getsockopt(level, optname[, buflen])

返回给定套接字选项的值(参见Unix手册页 getsockopt(2))。所需的符号常量(SO_* 等)在本模块中定义。如果 buflen 不存在,则假定为整数选项,并且函数返回其整数值。如果 buflen 存在,它指定用于接收选项的缓冲区的最大长度,并且该缓冲区作为字节对象返回。它由调用者解码缓冲区的内容(参见可选的内置模块 struct,用于解码编码为字节字符串的C结构)。

socket.gettimeout()

返回与套接字操作相关联的超时(以秒为单位)(float),如果未设置超时,则返回 None。这反映了最后一次调用 setblocking()settimeout()

socket.ioctl(control, option)
Platform:

视窗

ioctl() 方法是到WSAIoctl系统接口的有限接口。有关详细信息,请参阅 Win32文档

在其他平台上,可以使用通用 fcntl.fcntl()fcntl.ioctl() 功能;他们接受一个套接字对象作为它们的第一个参数。

目前仅支持以下控制代码:SIO_RCVALLSIO_KEEPALIVE_VALSSIO_LOOPBACK_FAST_PATH

在 3.6 版更改: 加入 SIO_LOOPBACK_FAST_PATH

socket.listen([backlog])

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

在 3.5 版更改: backlog 参数现在是可选的。

socket.makefile(mode='r', buffering=None, *, encoding=None, errors=None, newline=None)

返回与套接字相关联的 file object。确切返回的类型取决于给予 makefile() 的参数。这些参数以与内置 open() 函数相同的方式解释,除了仅支持的 mode 值为 'r' (默认),'w''b'

套接字必须处于阻塞模式;它可以有一个超时,但如果超时发生,文件对象的内部缓冲区可能会出现不一致的状态。

关闭由 makefile() 返回的文件对象将不会关闭原始套接字,除非所有其他文件对象都已关闭,并且在套接字对象上调用了 socket.close()

注解

在Windows上,由 makefile() 创建的类文件对象不能用于具有文件描述符的文件对象,例如 subprocess.Popen() 的流参数。

socket.recv(bufsize[, flags])

从套接字接收数据。返回值是表示接收到的数据的字节对象。一次性接收的最大数据量由 bufsize 指定。有关可选参数 flags 的含义,请参见Unix手册页 recv(2);它默认为零。

注解

为了与硬件和网络现实最佳匹配,bufsize 的值应该是2的相对小的功率,例如4096。

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.recvfrom(bufsize[, flags])

从套接字接收数据。返回值是一对 (bytes, address),其中 bytes 是表示接收到的数据的字节对象,address 是发送数据的套接字的地址。有关可选参数 flags 的含义,请参见Unix手册页 recv(2);它默认为零。 (address 的格式取决于地址族 - 见上文。)

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.recvmsg(bufsize[, ancbufsize[, flags]])

从套接字接收正常数据(最多 bufsize 字节)和辅助数据。 ancbufsize 参数设置用于接收辅助数据的内部缓冲区的大小(以字节为单位);它默认为0,这意味着不会接收辅助数据。可以使用 CMSG_SPACE()CMSG_LEN() 计算辅助数据的适当缓冲区大小,并且不适合缓冲区的项目可能被截断或丢弃。 flags 参数默认为0,具有与 recv() 相同的含义。

返回值是一个4元组:(data, ancdata, msg_flags, address)data 项是保存接收的非辅助数据的 bytes 对象。 ancdata 项是表示接收到的辅助数据(控制消息)的零个或多个元组 (cmsg_level, cmsg_type, cmsg_data) 的列表:cmsg_levelcmsg_type 分别是指定协议级别和协议特定类型的整数,并且 cmsg_data 是保存相关联数据的 bytes 对象。 msg_flags 项是指示接收到的消息的条件的各种标志的按位或;有关详细信息,请参阅系统文档。如果接收套接字未连接,则 address 是发送套接字的地址(如果可用);否则,其值未指定。

在某些系统上,sendmsg()recvmsg() 可用于在 AF_UNIX 套接字上的进程之间传递文件描述符。当使用这种设施(通常限于 SOCK_STREAM 套接字)时,recvmsg() 将在其辅助数据中返回 (socket.SOL_SOCKET, socket.SCM_RIGHTS, fds) 形式的项,其中 fds 是表示新文件描述符的 bytes 对象,作为本地C int 的二进制数组类型。如果 recvmsg() 在系统调用返回后引发异常,它将首先尝试关闭通过此机制接收的任何文件描述符。

一些系统不指示仅部分接收的辅助数据项的截短长度。如果一个项目出现超出缓冲区的末尾,recvmsg() 将发出一个 RuntimeWarning,并返回它在缓冲区内的部分,只要它在相关数据开始之前没有被截断。

在支持 SCM_RIGHTS 机制的系统上,以下功能将接收高达 maxfds 文件描述符,返回消息数据和包含描述符的列表(同时忽略意外情况,例如接收到不相关的控制消息)。参见 sendmsg()

import socket, array

def recv_fds(sock, msglen, maxfds):
    fds = array.array("i")   # Array of ints
    msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize))
    for cmsg_level, cmsg_type, cmsg_data in ancdata:
        if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS):
            # Append data, ignoring any truncated integers at the end.
            fds.fromstring(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
    return msg, list(fds)

可用性:大多数Unix平台,可能是其他平台。

3.3 新版功能.

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.recvmsg_into(buffers[, ancbufsize[, flags]])

从套接字接收正常数据和辅助数据,表现为 recvmsg(),但将非辅助数据分散到一系列缓冲区中,而不是返回一个新的字节对象。 buffers 参数必须是导出可写缓冲区(例如 bytearray 对象)的对象的可迭代对象;这些将被填充有非辅助数据的连续块,直到它被全部写入或没有更多的缓冲器。操作系统可以对可以使用的缓冲器的数量设置限制(sysconf()SC_IOV_MAX)。 ancbufsizeflags 参数具有与 recvmsg() 相同的含义。

返回值是一个4元组:(nbytes, ancdata, msg_flags, address),其中 nbytes 是写入缓冲区的非辅助数据的字节总数,ancdatamsg_flagsaddressrecvmsg() 相同。

例:

>>> import socket
>>> s1, s2 = socket.socketpair()
>>> b1 = bytearray(b'----')
>>> b2 = bytearray(b'0123456789')
>>> b3 = bytearray(b'--------------')
>>> s1.send(b'Mary had a little lamb')
22
>>> s2.recvmsg_into([b1, memoryview(b2)[2:9], b3])
(22, [], 0, None)
>>> [b1, b2, b3]
[bytearray(b'Mary'), bytearray(b'01 had a 9'), bytearray(b'little lamb---')]

可用性:大多数Unix平台,可能是其他平台。

3.3 新版功能.

socket.recvfrom_into(buffer[, nbytes[, flags]])

从套接字接收数据,将其写入 buffer,而不是创建一个新的字节。返回值是一对 (nbytes, address),其中 nbytes 是接收的字节数,address 是发送数据的套接字的地址。有关可选参数 flags 的含义,请参见Unix手册页 recv(2);它默认为零。 (address 的格式取决于地址族 - 见上文。)

socket.recv_into(buffer[, nbytes[, flags]])

从套接字接收到 nbytes 字节,将数据存储到缓冲区中,而不是创建新的字节。如果未指定 nbytes (或0),则接收达到给定缓冲区中可用的大小。返回接收的字节数。有关可选参数 flags 的含义,请参见Unix手册页 recv(2);它默认为零。

socket.send(bytes[, flags])

将数据发送到套接字。插座必须连接到远程插座。可选的 flags 参数具有与上述 recv() 相同的含义。返回发送的字节数。应用程序负责检查所有数据是否已发送;如果仅传输了一些数据,则应用程序需要尝试传递剩余的数据。有关此主题的更多信息,请咨询 套接字编程HOWTO

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.sendall(bytes[, flags])

将数据发送到套接字。插座必须连接到远程插座。可选的 flags 参数具有与上述 recv() 相同的含义。与 send() 不同,此方法继续从 bytes 发送数据,直到所有数据已发送或发生错误。成功返回 None。出现错误时,会引发异常,并且无法确定已成功发送多少数据(如果有)。

在 3.5 版更改: 每次数据成功发送时,套接字超时不再重置。套接字超时现在是发送所有数据的最大总持续时间。

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.sendto(bytes, address)
socket.sendto(bytes, flags, address)

将数据发送到套接字。由于目标套接字由 address 指定,因此套接字不应连接到远程套接字。可选的 flags 参数具有与上述 recv() 相同的含义。返回发送的字节数。 (address 的格式取决于地址系列 - 见上文。)

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.sendmsg(buffers[, ancdata[, flags[, address]]])

将正常和辅助数据发送到套接字,从一系列缓冲区收集非辅助数据,并将其连接到单个消息中。 buffers 参数将非辅助数据指定为 字节状对象 的可迭代(例如,bytes 对象);操作系统可以对可以使用的缓冲器的数量设置限制(sysconf()SC_IOV_MAX)。 ancdata 自变量将辅助数据(控制消息)指定为零个或多个元组 (cmsg_level, cmsg_type, cmsg_data) 的可迭代,其中 cmsg_levelcmsg_type 是分别指定协议级别和协议特定类型的整数,cmsg_data 是保存相关联数据的类似字节的对象。注意,一些系统(特别是,没有 CMSG_SPACE() 的系统)可能支持每次呼叫仅发送一个控制消息。 flags 参数默认为0,其含义与 send() 相同。如果提供了 address 而不是 None,则它设置消息的目标地址。返回值是发送的非辅助数据的字节数。

以下函数在支持 SCM_RIGHTS 机制的系统上通过 AF_UNIX 套接字发送文件描述符 fds 的列表。参见 recvmsg()

import socket, array

def send_fds(sock, msg, fds):
    return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))])

可用性:大多数Unix平台,可能是其他平台。

3.3 新版功能.

在 3.5 版更改: 如果系统调用中断并且信号处理程序不引发异常,则该方法现在重试系统调用,而不是引发 InterruptedError 异常(请参阅 PEP 475 的原因)。

socket.sendmsg_afalg([msg, ]*, op[, iv[, assoclen[, flags]]])

用于 AF_ALG 插座的 sendmsg() 专用版本。设置模式,IV,AEAD关联的数据长度和 AF_ALG 套接字的标志。

可用性:Linux> = 2.6.38

3.6 新版功能.

socket.sendfile(file, offset=0, count=None)

使用高性能 os.sendfile 发送文件,直到到达EOF,并返回发送的总字节数。 file 必须是以二进制模式打开的常规文件对象。如果 os.sendfile 不可用(例如Windows)或 file 不是常规文件,将改为使用 send()offset 告诉从哪里开始读取文件。如果指定,count 是要发送的字节的总数,而不是发送文件,直到到达EOF。文件位置在返回时被更新,或者在错误的情况下被更新,在这种情况下,可以使用 file.tell() 来计算发送的字节数。插座必须是 SOCK_STREAM 类型。不支持非阻塞套接字。

3.5 新版功能.

socket.set_inheritable(inheritable)

设置套接字文件描述符或套接字句柄的 继承标志

3.4 新版功能.

socket.setblocking(flag)

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

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

  • sock.setblocking(True) 等价于 sock.settimeout(None)

  • sock.setblocking(False) 等价于 sock.settimeout(0.0)

socket.settimeout(value)

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

有关更多信息,请咨询 注意套接字超时

socket.setsockopt(level, optname, value: int)
socket.setsockopt(level, optname, value: buffer)
socket.setsockopt(level, optname, None, optlen: int)

设置给定套接字选项的值(参见Unix手册页 setsockopt(2))。所需的符号常量在 socket 模块(SO_* 等)中定义。该值可以是表示缓冲区的整数,Nonebytes-like object。在后一种情况下,由调用者确保字节包含正确的位(参见可选的内置模块 struct,用于将C结构编码为bytestrings)。当value设置为 None 时,需要optlen参数。它相当于调用setsockopt C函数,optval = NULL和optlen = optlen。

在 3.5 版更改: 可写 bytes-like object 现已被接受。

在 3.6 版更改: setsockopt(level,optname,None,optlen:int)表单。

socket.shutdown(how)

关闭连接的一半或两半。如果 howSHUT_RD,则不允许进一步接收。如果 howSHUT_WR,则不允许进一步发送。如果 howSHUT_RDWR,则不允许进一步发送和接收。

socket.share(process_id)

复制套接字并准备与目标进程共享。目标流程必须提供 process_id。然后可以使用某种形式的进程间通信将生成的字节对象传递到目标进程,并且可以使用 fromshare() 在那里重新创建套接字。调用此方法后,可以安全地关闭套接字,因为操作系统已经为目标进程复制了它。

可用性:Windows。

3.3 新版功能.

注意没有方法 read()write();使用没有 flags 参数的 recv()send()

Socket对象还具有对应于给予 socket 构造函数的值的这些(只读)属性。

socket.family

插座系列。

socket.type

套接字类型。

socket.proto

套接字协议。

18.1.4. 套接字超时的注意事项

套接字对象可以是以下三种模式之一:阻塞,非阻塞或超时。默认情况下,套接字始终在阻塞模式下创建,但可以通过调用 setdefaulttimeout() 来更改。

  • 阻塞模式 中,操作阻塞直到完成或系统返回错误(例如连接超时)。

  • 非阻塞模式 中,如果无法立即完成操作,那么操作将失败(错误是与系统相关的错误):来自 select 的函数可用于知道套接字何时可用于读取或写入。

  • 超时模式 中,如果无法在为套接字指定的超时(它们引发 timeout 异常)或系统返回错误时无法完成操作,则操作将失败。

注解

在操作系统级别,超时模式 中的套接字在内部设置为非阻塞模式。此外,阻塞和超时模式在引用同一网络端点的文件描述符和套接字对象之间共享。该实现细节可以具有可见的后果,例如您决定使用套接字的 fileno()

18.1.4.1. 超时和 connect 方法

connect() 操作也受超时设置的约束,并且通常建议在调用 connect() 之前调用 settimeout() 或将超时参数传递给 create_connection()。但是,系统网络堆栈也可能返回其自身的连接超时错误,而不管任何Python套接字超时设置。

18.1.4.2. 超时和 accept 方法

如果 getdefaulttimeout() 不是 None,则 accept() 方法返回的套接字继承该超时。否则,行为取决于侦听套接字的设置:

  • 如果侦听套接字在 阻塞模式超时模式 中,则由 accept() 返回的套接字在 阻塞模式 中;

  • 如果侦听套接字在 非阻塞模式 中,则 accept() 返回的套接字是处于阻塞还是非阻塞模式是操作系统相关的。如果要确保跨平台行为,建议您手动覆盖此设置。

18.1.5. 例

下面是使用TCP/IP协议的四个最小示例程序:一个服务器,它回送它接收的所有数据(仅服务一个客户端),以及使用它的客户端。注意,服务器必须执行序列 socket()bind()listen()accept() (可能重复 accept() 以服务多于一个客户端),而客户端仅需要序列 socket()connect()。还要注意,服务器不是 sendall()/recv() 在套接字它正在侦听,但在由 accept() 返回的新套接字。

前两个示例仅支持IPv4。

# Echo server program
import socket

HOST = ''                 # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen(1)
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data: break
            conn.sendall(data)
# Echo client program
import socket

HOST = 'daring.cwi.nl'    # The remote host
PORT = 50007              # The same port as used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'Hello, world')
    data = s.recv(1024)
print('Received', repr(data))

接下来的两个示例与上述两个示例相同,但支持IPv4和IPv6。服务器端将侦听可用的第一个地址系列(它应该侦听两个地址系列)。在大多数IPv6就绪系统上,IPv6将优先,服务器可能不接受IPv4流量。客户端将尝试连接到作为名称解析的结果返回的所有地址,并向成功连接的第一个地址发送流量。

# Echo server program
import socket
import sys

HOST = None               # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC,
                              socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
    af, socktype, proto, canonname, sa = res
    try:
        s = socket.socket(af, socktype, proto)
    except OSError as msg:
        s = None
        continue
    try:
        s.bind(sa)
        s.listen(1)
    except OSError as msg:
        s.close()
        s = None
        continue
    break
if s is None:
    print('could not open socket')
    sys.exit(1)
conn, addr = s.accept()
with conn:
    print('Connected by', addr)
    while True:
        data = conn.recv(1024)
        if not data: break
        conn.send(data)
# Echo client program
import socket
import sys

HOST = 'daring.cwi.nl'    # The remote host
PORT = 50007              # The same port as used by the server
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
    af, socktype, proto, canonname, sa = res
    try:
        s = socket.socket(af, socktype, proto)
    except OSError as msg:
        s = None
        continue
    try:
        s.connect(sa)
    except OSError as msg:
        s.close()
        s = None
        continue
    break
if s is None:
    print('could not open socket')
    sys.exit(1)
with s:
    s.sendall(b'Hello, world')
    data = s.recv(1024)
print('Received', repr(data))

下一个例子显示了如何在Windows上编写一个非常简单的网络嗅探器和原始套接字。该示例需要管理员权限才能修改接口:

import socket

# the public network interface
HOST = socket.gethostbyname(socket.gethostname())

# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))

# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# receive a package
print(s.recvfrom(65565))

# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

最后一个示例显示如何使用套接字接口使用原始套接字协议与CAN网络通信。要使用CAN与广播管理器协议,而是打开一个套接字:

socket.socket(socket.AF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM)

在绑定(CAN_RAW)或连接(CAN_BCM)套接字后,您可以照常使用 socket.send()socket.recv() 操作(及其对应的)套接字对象。

此示例可能需要特殊权限:

import socket
import struct


# CAN frame packing/unpacking (see 'struct can_frame' in <linux/can.h>)

can_frame_fmt = "=IB3x8s"
can_frame_size = struct.calcsize(can_frame_fmt)

def build_can_frame(can_id, data):
    can_dlc = len(data)
    data = data.ljust(8, b'\x00')
    return struct.pack(can_frame_fmt, can_id, can_dlc, data)

def dissect_can_frame(frame):
    can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame)
    return (can_id, can_dlc, data[:can_dlc])


# create a raw socket and bind it to the 'vcan0' interface
s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
s.bind(('vcan0',))

while True:
    cf, addr = s.recvfrom(can_frame_size)

    print('Received: can_id=%x, can_dlc=%x, data=%s' % dissect_can_frame(cf))

    try:
        s.send(cf)
    except OSError:
        print('Error sending CAN frame')

    try:
        s.send(build_can_frame(0x01, b'\x01\x02\x03'))
    except OSError:
        print('Error sending CAN frame')

运行示例多次,执行之间的延迟太小,可能会导致此错误:

OSError: [Errno 98] Address already in use

这是因为先前的执行已经使套接字处于 TIME_WAIT 状态,并且不能立即重用。

有一个 socket 标志要设置,以防止这种情况,socket.SO_REUSEADDR:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))

SO_REUSEADDR 标志告诉内核重用 TIME_WAIT 状态中的本地套接字,而不等待其自然超时到期。

参见

有关套接字编程(C语言)的介绍,请参阅以下文件:

  • 介绍4.3BSD进程间通信教程,作者:Stuart Sechrest

  • 高级4.3BSD进程间通信教程,by Samuel J.Leffler et al,

在UNIX程序员手册,补充文件1(PS1:7和PS1:8章节)。用于各种套接字相关系统调用的平台特定参考资料也是套接字语义的细节的有价值的信息来源。对于Unix,请参见手册页;对于Windows,请参阅WinSock(或Winsock 2)规范。对于IPv6就绪的API,读者可能想参考 RFC 3493 标题为IPv6的基本套接字扩展。