18.1. socket — 底层网络接口

源代码: Lib / socket.py

这个模块提供访问BSD 套接字(socket) 的接口。它适用于所有现代Unix系统,Windows,MacOs及其他可能的平台。

注意

由于某些调用使用了操作系统的socket APIs,一些特性是依赖于特定平台的。

这个Python接口直接将套接字的Unix系统调用和库接口翻译成Python的面向对象风格:socket() 函数返回一个 socket 对象,这个对象的方法实现了不同的套接字系统调用。其中,一些参数类型比对应的C接口更高级:如对Python文件对象的 read()write() 操作,接收操作中缓冲区分配是自动的, 发送操作中缓冲区长度是隐含的。

另请参阅

socketserver模块
简化写作网络服务器的类。
ssl模块
套接字对象的 TLS/SSL 封装。

18.1.1. Socket 协议族

该模块支持何种socket协议族取决于系统与编译选项。

当一个socket对象被创建时,该socket对象所需的地址格式会根据特定的地址族被自动选择。Socket 地址被表示为:

  • 一个绑定到文件系统节点的 AF_UNIX 套接字的地址被表示为一个字符串,这个字符串使用文件系统编码与 'surrogateescape' 错误处理器 (see PEP 383).一个Linux抽象命名空间中的地址被作为一个被初始化为空字节的bytes-like object 返回;注意命名空间中的这些地址可以与常规文件系统套接字通讯,因此打算运行在Linux上的程序需要能同时处理两种类型的地址。当作为个一参数传递时,一个字符串或类字节对象可以被用做任意类型的地址。

    3.3 版本中的更改︰ AF_UNIX 套接字路径先前均假定使用 utf-8 编码。

    3.5 版本中的更改︰ 现在接受可写入的 bytes-like object

  • 一对参数 (host, port)用于 AF_INET 地址族, 其中host是一个字符串,表示在internet中像 'daring.cwi.nl'这样的域名 或 像'100.50.200.5'这样的IPv4地址, port(端口)参数是一个整数.

  • 对于 AF_INET6 地址族, 一个地址被表示为一个四维元组 (host, port, flowinfo, scopeid) , 其中, flowinfoscopeid 分别代表C中struct sockaddr_in6结构体中的成员 sin6_flowinfosin6_scope_id 。 为了向后兼容,在 socket 模块的方法中, flowinfoscopeid 参数可以被省略。但是请注意,忽略 scopeid 参数会导致操作IPv6地址时出现问题。

  • AF_NETLINK 套接字被表示为一个二维元组 (pid, groups).

  • 只有 Linux 支持的 TIPC 需要使用 AF_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和unit号已知或者使用已注册ID,那么元祖可以被使用。

    3.3 版本中新加入。

  • AF_BLUETOOTH 支持下列协议和地址格式︰

    • BTPROTO_L2CAP接受(bdaddr, psm)其中bdaddr字符串和psm是一个整数。

    • BTPROTO_RFCOMM接受(bdaddr, 通道)其中bdaddr字符串和channel是一个整数。

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

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

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

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

在表示IPv4地址时,可以采用两种特殊的字符串形式来表示特定的主机地址:用空字符串表示INADDR_ANY;用字符串'<broadcast>'来表示INADDR_BROADCAST此行为与IPv6不兼容,因此,如果您打算使用Python程序支持IPv6,则可能希望避免这些行为。

如果在IPv4 / v6套接字地址的主机部分中使用主机名,则程序可能显示非确定性行为,因为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()会引发与地址相关的错误。伴随的值是表示库调用返回的错误的一对(错误, 字符串)string表示由gai_strerror() C函数返回的错误的描述。数字错误值将匹配此模块中定义的EAI_*常量之一。

在版本3.3中已更改:此类已成为OSError的子类。

exception socket.timeout

OSError的子类,当通过先前调用settimeout()(或隐含地通过setdefaulttimeout())。附带的值是一个字符串,其值目前总是“超时”。

在版本3.3中已更改:此类已成为OSError的子类。

18.1.2.2. 常量

The AF_* and SOCK_* constants are now AddressFamily and SocketKind IntEnum collections.

New in version 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头文件中定义的那些符号;对于几个符号,提供默认值。

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中的新功能。

SIO _ *
RCVALL _ *

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

TIPC _ *

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

可用性: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. 创建 sockets

以下函数都可以创建socket 对象.

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

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

新创建的套接字non-inheritable

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

Changed in version 3.4:增加了CAN_BCM 协议 .

Changed in version 3.4:返回的socket现在是不可继承的.

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

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

新创建的套接字non-inheritable

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

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

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

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

连接到互联网上侦听的TCP服务地址(2元组(主机, 端口) 并返回套接字对象。This is a higher-level function than socket.connect(): if host is a non-numeric hostname, it will try to resolve it for both AF_INET and AF_INET6, and then try to connect to all possible addresses in turn until a connection succeeds. 这使得编写与IPv4和IPv6兼容的客户端变得容易。

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

如果提供,source_address必须是2元组(主机, 端口) 其源地址连接前。如果主机或端口分别为''或0,将使用操作系统默认行为。

在版本3.2中更改: source_address已添加。

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

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

新创建的套接字non-inheritable

在版本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)

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

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

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

(family, type, proto, canonname, sockaddr) / t0>

在这些元组中,family类型proto都是整数并且传递给socket()如果AI_CANONNAMEflags参数的一部分,canonname将是表示主机的规范名称的字符串; else canonname将为空。sockaddr is a tuple describing a socket address, whose format depends on the returned family (a (address, port) 2-tuple for AF_INET, a (address, port, flow info, scope id) 4-tuple for AF_INET6), and is meant to be passed to the socket.connect() method.

以下示例为端口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])

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

socket.gethostbyname(hostname)

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

socket.gethostbyname_ex(hostname)

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

socket.gethostname()

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

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

socket.gethostbyaddr(ip_address)

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

socket.getnameinfo(sockaddr, flags)

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

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位正整数从网络字节顺序转换为主机字节顺序。

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的对象(即C类型) 32位打包二进制这个函数返回。

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的对象(即C类型) 32位打包二进制数据此函数作为参数。

如果传递给此函数的字节序列的长度不完全为4个字节,则会引发OSErrorinet_ntoa()不支持IPv6,而应使用inet_ntop()替代IPv4 / v6双栈支持。

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

socket.inet_pton(address_family, ip_string)

将IP地址从其特定类型的字符串格式转换为压缩的二进制格式。inet_pton() is useful when a library or network protocol calls for an object of type struct in_addr (similar to inet_aton()) or struct in6_addr.

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() is useful when a library or network protocol returns an object of type struct in_addr (similar to inet_ntoa()) or struct in6_addr.

address_family的支持值目前为AF_INETAF_INET6如果字节对象packed_ip不是指定地址系列的正确长度,则会引发ValueError对来自inet_ntop()的调用的错误引发OSError

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

在版本3.4中已更改:添加了Windows支持

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

socket.CMSG_LEN(length)

返回具有给定长度的关联数据的辅助数据项的总长度,而不使用尾随填充。此值通常可用作recvmsg()的缓冲区大小,以接收单个辅助数据项,但 RFC 3542需要可移植应用程序使用CMSG_SPACE(),因此包括用于填充的空间,即使项目将是缓冲区中的最后一个。引发OverflowError如果长度超出允许的值范围。

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

版本3.3中的新功能。

socket.CMSG_SPACE(length)

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

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

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

版本3.3中的新功能。

socket.getdefaulttimeout()

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

socket.setdefaulttimeout(timeout)

为新的套接字对象设置默认超时(以秒为单位)(float)。首次导入插槽模块时,默认值为None有关可能的值及其各自含义,请参见settimeout()

socket.sethostname(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 对象

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

在版本3.2中已更改:添加了对context manager协议的支持。退出上下文管理器等效于调用close()

socket.accept()

接收一个连接.该socket 必须要绑定一个地址和监听连接.返回值是一对(conn, 地址)其中conn新 t4 > socket对象可用于在连接上发送和接收数据,address是连接另一端的套接字的地址。

新创建的套接字non-inheritable

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

在版本3.5中更改:如果系统调用中断并且信号处理程序没有引发异常,则此方法现在重试系统调用,而不是引发InterruptedError异常 PEP 475)。

socket.bind(address)

将套接字绑定到地址套接字必须尚未绑定。地址的格式取决于地址系列 - 请参见上文)

socket.close()

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

套接字在被垃圾回收时自动关闭,但建议显式地close(),或者在打开套接字时使用with语句。

注意

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

socket.connect(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()

复制套接字。

新创建的套接字non-inheritable

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

socket.fileno()

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

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

socket.get_inheritable()

获取套接字文件的inheritable flag描述器或套接字句柄: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)
平台:视窗

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

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

socket.listen([backlog])

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

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

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

返回与套接字相关联的file object确切返回的类型取决于给予makefile()的参数。These arguments are interpreted the same way as by the built-in open() function, except the only supported mode values are 'r' (default), 'w' and '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])

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

在版本3.5中更改:如果系统调用中断并且信号处理程序没有引发异常,则此方法现在重试系统调用,而不是引发InterruptedError异常 PEP 475)。

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

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

返回值是一个4元组:(数据, ancdata, msg_flags, 地址) / t0>。数据项是持有所接收的非辅助数据的bytes对象。The ancdata item is a list of zero or more tuples (cmsg_level, cmsg_type, cmsg_data) representing the ancillary data (control messages) received: cmsg_level and cmsg_type are integers specifying the protocol level and protocol-specific type respectively, and cmsg_data is a bytes object holding the associated data. msg_flags项是指示接收到的消息上的条件的各种标志的按位或;有关详细信息,请参阅系统文档。如果接收套接字未连接,则地址是发送套接字的地址(如果可用);否则,其值未指定。

在一些系统上,sendmsg()recvmsg()可用于在AF_UNIXWhen this facility is used (it is often restricted to SOCK_STREAM sockets), recvmsg() will return, in its ancillary data, items of the form (socket.SOL_SOCKET, socket.SCM_RIGHTS, fds), where fds is a bytes object representing the new file descriptors as a binary array of the native C int type. 如果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 objects);这些将被非辅助数据的连续块填充,直到它被全部写入或没有更多的缓冲器。操作系统可以对可以使用的缓冲区数量设置限制(sysconf() value SC_IOV_MAX)。ancbufsize标志参数与recvmsg()具有相同的含义。

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

例:

>>> 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]])

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

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

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

socket.send(bytes[, flags])

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

在版本3.5中更改:如果系统调用中断并且信号处理程序没有引发异常,则此方法现在重试系统调用,而不是引发InterruptedError异常 PEP 475)。

socket.sendall(bytes[, flags])

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

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

在版本3.5中更改:如果系统调用中断并且信号处理程序没有引发异常,则此方法现在重试系统调用,而不是引发InterruptedError异常 PEP 475)。

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

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

在版本3.5中更改:如果系统调用中断并且信号处理程序没有引发异常,则此方法现在重试系统调用,而不是引发InterruptedError异常 PEP 475)。

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

将正常和辅助数据发送到套接字,从一系列缓冲区收集非辅助数据,并将其连接到单个消息中。buffers参数指定非辅助数据作为bytes-like objects(例如,bytes对象);操作系统可以对可以使用的缓冲区的数量设置限制(sysconf()SC_IOV_MAX)。The ancdata argument specifies the ancillary data (control messages) as an iterable of zero or more tuples (cmsg_level, cmsg_type, cmsg_data), where cmsg_level and cmsg_type are integers specifying the protocol level and protocol-specific type respectively, and cmsg_data is a bytes-like object holding the associated data. 请注意,一些系统(特别是没有CMSG_SPACE()的系统)可能支持每次调用仅发送一个控制消息。flags参数默认为0,含义与send()相同。如果提供地址,而不是None,则它设置消息的目标地址。返回值是发送的非辅助数据的字节数。

The following function sends the list of file descriptors fds over an AF_UNIX socket, on systems which support the SCM_RIGHTS mechanism. 另请参见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.sendfile(file, offset=0, count=None)

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

版本3.5中的新功能。

socket.set_inheritable(inheritable)

设置套接字文件描述器或套接字句柄的inheritable flag

版本3.4中的新功能。

socket.setblocking(flag)

设置阻塞或非阻塞套接字模式t: 如果 flag 为假, 该套接字设置为无阻塞,否则成阻塞模式.:

此方法确切来说是 settimeout() 调用函数的简写形式:

  • sock.setblocking(True) 相当于 sock.settimeout(None)
  • sock.setblocking(False) 相当于 sock.settimeout(0.0)
socket.settimeout(value)

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

有关详细信息,请参阅notes on socket timeouts

socket.setsockopt(level, optname, value)

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

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

socket.shutdown(how)

关闭连接的一半或两半。如果如何SHUT_RD,则不允许进一步接收。如果如何SHUT_WR,则不允许进一步发送。如果如何SHUT_RDWR,则不允许进一步发送和接收。

socket.share(process_id)

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

可用性:Windows。

版本3.3中的新功能。

注意,没有方法read()write();请使用recv()send()而不使用flags参数。

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

socket.family

插座系列。

socket.type

套接字类型。

socket.proto

套接字协议。

18.1.4. Notes on socket timeouts

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

  • 阻塞模式中,操作阻塞直到完成或系统返回错误(例如连接超时)。
  • 非阻塞模式中,如果无法立即完成操作,则操作将失败(具有与系统相关的错误):select的函数可用于了解何时以及插座是否可用于读取或写入。
  • 超时模式中,如果无法在为套接字指定的超时(它们引发timeout异常)或系统返回错误时无法完成操作,则操作将失败。

注意

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

18.1.4.1. Timeouts and the connect method

The connect() operation is also subject to the timeout setting, and in general it is recommended to call settimeout() before calling connect() or pass a timeout parameter to create_connection(). 但是,系统网络堆栈也可能返回其自己的连接超时错误,而不管任何Python套接字超时设置。

18.1.4.2. Timeouts and the accept method

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

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

18.1.5. Example

下面是使用TCP / IP协议的四个最小示例程序:一个服务器,它回送它接收的所有数据(仅服务一个客户端),以及使用它的客户端。Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by 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
  • Advanced Advanced 4.3BSD Interprocess Communication Tutorial,由Samuel J.Leffler等人,

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