17.2. 套接字—低级网络接口

该模块提供对 BSD * socket *接口的访问。它在所有现代 Unix 系统,Windows,Mac OS X,BeOS,OS/2 以及可能的其他平台上都可用。

Note

由于对 os 套接字 API 进行了调用,因此某些行为可能取决于平台。

有关套接字编程(用 C 语言编写)的介绍,请参见以下文章:UNIX 程序员手册中的 Stuart Sechrest 撰写的 4.3BSD 进程间通信入门教程和 Samuel J. Leffler 等人的 Sam 4.3 JSD 的 Advanced 4.3BSD 进程间通信教程。 ,补充文件 1(PS1:7 和 PS1:8 部分)。各种与套接字相关的系统调用的特定于平台的参考资料也是有关套接字语义细节的有价值的信息来源。对于 Unix,请参考手册页。对于 Windows,请参阅 WinSock(或 Winsock 2)规范。对于支持 IPv6 的 API,Reader 可能希望参考 RFC 3493标题为 IPv6 的基本套接字接口扩展。

Python 接口是 Unix 系统调用和库接口的直接转译,用于将套接字转换为 Python 的面向对象样式:socket()函数返回* socket 对象*,其方法实现了各种套接字系统调用。参数类型比 C 接口中的级别更高:与 Python 文件上的read()write()操作一样,接收操作的缓冲区分配是自动的,发送操作的缓冲区长度是隐式的。

套接字地址表示如下:AF_UNIX地址系列使用单个字符串。对(host, port)用于AF_INET地址族,其中* host 是一个字符串,表示 Internet 域表示法中的主机名(如'daring.cwi.nl')或 IPv4 地址(如'100.50.200.5'),而 port 是整数。对于AF_INET6地址族,使用四 Tuples(host, port, flowinfo, scopeid),其中 flowinfo scopeid 表示 C 中struct sockaddr_in6中的sin6_flowinfosin6_scope_id成员。对于socket模块方法,仅出于向后兼容性,可以Ellipsis flowinfo scopeid * 。但是请注意,Ellipsis* scopeid *可能会导致在处理作用域 IPv6 地址时出现问题。当前不支持其他地址族。将根据创建套接字对象时指定的地址系列自动选择特定套接字对象所需的地址格式。

对于 IPv4 地址,可以接受两种特殊形式而不是主机地址:空字符串表示INADDR_ANY,而字符串'<broadcast>'表示INADDR_BROADCAST。该行为不适用于 IPv6 以实现向后兼容性,因此,如果要使用 Python 程序支持 IPv6,则可能要避免这些行为。

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

2.5 版中的新Function:AF_NETLINK 套接字表示为对pid, groups

2.6 版中的新Function:使用AF_TIPC地址系列也可提供仅 Linux 对 TIPC 的支持。 TIPC 是一种开放的,非基于 IP 的网络协议,旨在用于群集计算机环境中。地址由 Tuples 表示,并且字段取决于地址类型。一般的 Tuples 形式为(addr_type, v1, v2, v3 [, scope]),其中:

    • addr_type *是TIPC_ADDR_NAMESEQTIPC_ADDR_NAMETIPC_ADDR_ID之一。
    • scope *是TIPC_ZONE_SCOPETIPC_CLUSTER_SCOPETIPC_NODE_SCOPE之一。
  • 如果* addr_type TIPC_ADDR_NAME,则 v1 是服务器类型, v2 是端口标识符,而 v3 *应该为 0.

如果* addr_type TIPC_ADDR_NAMESEQ,则 v1 为服务器类型, v2 为下端口号, v3 *为上端口号。

如果* addr_type TIPC_ADDR_ID,则 v1 是节点, v2 是引用,并且 v3 *应该设置为 0.

所有错误都会引发异常。无效参数类型和内存不足条件的正常异常可以被提出。与套接字或地址语义相关的错误会引发错误socket.error

passsetblocking()支持非阻塞模式。passsettimeout()支持基于超时的通用化。

模块socket导出以下常量和函数:

  • exception socket. error
    • 针对与套接字相关的错误,引发此异常。随附的值可以是一个告诉错误的字符串,也可以是代表系统调用返回的错误的(errno, string)对,类似于os.error的值。请参阅模块errno,其中包含基础 os 定义的错误代码的名称。

在 2.6 版中更改:socket.error现在是IOError的子类。

  • exception socket. herror

附带的值是Pair(h_errno, string),代表库调用返回的错误。 * string 表示hstrerror() C 函数返回的 h_errno *的描述。

  • exception socket. gaierror

    • 针对地址相关的错误(getaddrinfo()getnameinfo())引发此异常。附带的值是对(error, string),代表由库调用返回的错误。 * string 表示gai_strerror() C 函数返回的 error *的描述。 * error *值将匹配此模块中定义的EAI_*常量之一。
  • exception socket. timeout

    • 当套接字发生超时时,如果pass先前调用settimeout()启用了超时,则会引发此异常。附带的值是一个字符串,其值当前始终处于“超时”状态。

2.3 版的新Function。

  • 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

  • SO_*

  • socket. SOMAXCONN

  • MSG_*

  • SOL_*

  • IPPROTO_*

  • IPPORT_*

  • INADDR_*

  • IP_*

  • IPV6_*

  • EAI_*

  • AI_*

  • NI_*

  • TCP_*

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

  • RCVALL_*

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

2.6 版的新Function。

  • TIPC_*

    • TIPC 相关的常量,与 C 套接字 API 导出的常量匹配。有关更多信息,请参见 TIPC 文档。

2.6 版的新Function。

  • socket. has_ipv6
    • 该常量包含一个布尔值,该值指示此平台上是否支持 IPv6.

2.3 版的新Function。

  • socket. create_connection(* address * [,* timeout * [,* source_address *]])
    • 连接到侦听 Internet 地址(2Tuples(host, port))的 TCP 服务,并返回套接字对象。这是比socket.connect()更高级别的函数:如果* host *是非数字主机名,它将try同时为AF_INETAF_INET6解析它,然后try依次连接到所有可能的地址,直到连接成功。这使得编写兼容 IPv4 和 IPv6 的 Client 端变得容易。

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

如果提供,则* source_address *必须为 2Tuples(host, port),以便套接字在连接之前绑定为其源地址。如果主机或端口分别为''或 0,则将使用 os 默认行为。

2.6 版的新Function。

在 2.7 版中进行了更改:添加了* source_address *。

  • socket. getaddrinfo(* host port * [,* family * [,* socktype * [,* proto * [,* flags *]]]))
    • 将* host / port *参数转换为 5Tuples 的序列,其中包含用于创建连接到该服务的套接字的所有必需参数。 * host *是域名,是 IPv4/v6 地址或None的字符串表示形式。 * port 是字符串服务名称,例如'http',数字端口号或None。pass将None作为 host port *的值传递,您可以将NULL传递给基础 C API。

可以选择指定* family socktype proto 参数,以缩小返回的地址列表。默认情况下,它们的值为0,这意味着将选择整个结果范围。 * flags 参数可以是AI_*常量中的一个或多个,并将影响结果的计算和返回方式。其默认值为0。例如,AI_NUMERICHOST将禁用域名解析,并且如果 host *是域名,则会引发错误。

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

(family, socktype, proto, canonname, sockaddr)

在这些 Tuples 中,* family socktype proto 都是整数,并应传递给socket()函数。如果AI_CANONNAME flags 参数的一部分,则* canonname 将是代表 host 规范名称的字符串;否则 canonname *将为空。 * sockaddr 是一个描述套接字地址的 Tuples,其格式取决于返回的 family *(对于AF_INET(address, port) 2Tuples,对于AF_INET6(address, port, flow info, scope id) 4Tuples),并打算传递给socket.connect()方法。

以下示例为端口 80 上与example.org的虚拟 TCP 连接获取地址信息(如果未启用 IPv6,结果可能会在您的系统上有所不同):

>>> socket.getaddrinfo("example.org", 80, 0, 0, socket.IPPROTO_TCP)
[(10, 1, 6, '', ('2606:2800:220:1:248:1893:25c8:1946', 80, 0, 0)),
 (2, 1, 6, '', ('93.184.216.34', 80))]

2.2 版中的新Function。

  • socket. getfqdn([* name *])
    • 返回* name 的完全限定域名。如果 name *被Ellipsis或为空,则将其解释为 localhost。要查找标准名称,请检查gethostbyaddr()返回的主机名,然后检查主机的别名(如果有)。选择包含句点的名字。如果没有完全限定的域名可用,则返回gethostname()返回的主机名。

2.0 版中的新Function。

  • 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 解释器当前正在执行的机器的主机名。

如果您想知道当前机器的 IP 地址,则可以使用gethostbyname(gethostname())。该操作假设主机存在有效的地址到主机 Map,并且该假设并不总是成立。

注意:gethostname()并不总是返回完全限定的域名。使用getfqdn()(请参见上文)。

  • socket. gethostbyaddr(* ip_address *)

    • 返回一个三 Tuples(hostname, aliaslist, ipaddrlist),其中* hostname 是响应给定 ip_address 的主要主机名, aliaslist 是该地址的替代主机名的列表(可能为空),而 ipaddrlist *是 IPv4 /同一主机上同一接口的 v6 地址(很可能仅包含一个地址)。要查找完全合格的域名,请使用函数getfqdn()gethostbyaddr()支持 IPv4 和 IPv6.
  • socket. getnameinfo(* sockaddr flags *)

    • 将套接字地址* sockaddr 转换为 2Tuples(host, port)。根据 flags 的设置,结果可以在 host 中包含标准域名或数字地址表示形式。同样, port *可以包含字符串端口名称或数字端口号。

2.2 版中的新Function。

  • socket. getprotobyname(协议名称)

    • 将 Internet 协议名称(例如'icmp')转换为适合作为(可选的)第三个参数传递给socket()函数的常量。通常只有在“原始”模式(SOCK_RAW)中打开的套接字才需要使用此方法。对于正常的套接字模式,如果协议Ellipsis或为零,则会自动选择正确的协议。
  • socket. getservbyname(* servicename * [,* protocolname *])

    • 将 Internet 服务名称和协议名称转换为该服务的端口号。可选协议名称(如果提供)应为'tcp''udp',否则任何协议都将匹配。
  • socket. getservbyport(* port * [,* protocolname *])

    • 将 Internet 端口号和协议名称转换为该服务的服务名称。可选协议名称(如果提供)应为'tcp''udp',否则任何协议都将匹配。
  • socket. socket([* family * [,* type * [,* proto *]]])

    • 使用给定的地址族,套接字类型和协议号创建一个新的套接字。地址族应为AF_INET(默认值),AF_INET6AF_UNIX。套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM或其他SOCK_常量之一。协议编号通常为零,在这种情况下可以Ellipsis。
  • socket. socketpair([* family * [,* type * [,* proto *]]])

    • 使用给定的地址族,套接字类型和协议号构建Pair连接的套接字对象。地址族,套接字类型和协议号与上面的socket()函数相同。如果在平台上定义,则默认系列为AF_UNIX;否则,默认值为AF_INET。可用性:Unix。

2.4 版的新Function。

  • socket. fromfd(* fd family type * [,* proto *])

    • 复制文件 Descriptors* fd *(由文件对象的fileno()方法返回的整数),并根据结果构建一个套接字对象。地址族,套接字类型和协议号与上面的socket()函数相同。文件 Descriptors 应该引用一个套接字,但是未选中-如果文件 Descriptors 无效,则对该对象的后续操作可能会失败。很少需要此函数,但可以使用该函数在作为标准 Importing 或输出(例如由 Unix inet 守护程序启动的服务器)传递给程序的套接字上获取或设置套接字选项。假定套接字处于阻止模式。可用性:Unix。
  • socket. ntohl(* x *)

    • 将 32 位正整数从网络转换为主机字节 Sequences。在主机字节 Sequences 与网络字节 Sequences 相同的机器上,这是一个空操作;否则,它将执行 4 字节交换操作。
  • socket. ntohs(* x *)

    • 将 16 位正整数从网络转换为主机字节 Sequences。在主机字节 Sequences 与网络字节 Sequences 相同的机器上,这是一个空操作;否则,它将执行 2 字节交换操作。
  • socket. htonl(* x *)

    • 将主机的 32 位正整数转换为网络字节 Sequences。在主机字节 Sequences 与网络字节 Sequences 相同的机器上,这是一个空操作;否则,它将执行 4 字节交换操作。
  • socket. htons(* x *)

    • 将主机的 16 位正整数转换为网络字节 Sequences。在主机字节 Sequences 与网络字节 Sequences 相同的机器上,这是一个空操作;否则,它将执行 2 字节交换操作。
  • socket. inet_aton(* ip_string *)

    • 将 IPv4 地址从点分四进制字符串格式(例如'123.45.67.89')转换为 32 位压缩二进制格式,即长度为四个字符的字符串。与使用标准 C 库并且需要类型为struct in_addr的对象的程序进行对话时,此Function很有用。该对象是此函数返回的 32 位压缩二进制文件的 C 类型。

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

如果传递给此Function的 IPv4 地址字符串无效,则将引发socket.error。请注意,确切有效的内容取决于inet_aton()的基础 C 实现。

inet_aton()不支持 IPv6,而应使用inet_pton()代替 IPv4/v6 双协议栈。

  • socket. inet_ntoa(* packed_ip *)
    • 将 32 位压缩的 IPv4 地址(长度为四个字符的字符串)转换为其标准的点分四进制字符串表示形式(例如'123.45.67.89')。与使用标准 C 库且需要类型为struct in_addr的对象的程序进行对话时,此Function很有用。该对象是此函数作为参数的 32 位打包二进制数据的 C 类型。

如果传递给此函数的字符串长度不完全是 4 个字节,则将引发socket.errorinet_ntoa()不支持 IPv6,而应使用inet_ntop()代替 IPv4/v6 双栈。

  • 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 无效,则将引发socket.error。请注意,确切有效的内容取决于 address_family *的值和inet_pton()的基础实现。

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

2.3 版的新Function。

  • socket. inet_ntop(* address_family packed_ip *)
    • 当库或网络协议返回struct in_addr类型的对象(类似于inet_ntoa()时),将打包的 IP 地址(一些字符的字符串)转换为其标准的,特定于家庭的字符串表示形式(例如'7.10.0.5''5aef:2b::8')inet_ntop()很有用。 )或struct in6_addr

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

2.3 版的新Function。

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

2.3 版的新Function。

  • socket. setdefaulttimeout(* timeout *)
    • 为新的套接字对象设置默认超时(以秒为单位)(Float)。值None表示新的套接字对象没有超时。首次导入套接字模块时,默认值为None

2.3 版的新Function。

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

See also

  • Module SocketServer

  • 简化编写 Web Service 器的类。

  • Module ssl

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

17.2.1. 套接字对象

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

  • socket. accept ( )

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

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

Note

从历史上看,此方法接受了AF_INET个地址的Pair参数,而不仅仅是一个 Tuples。这从来不是故意的,并且在 Python 2.0 和更高版本中不再可用。

  • socket. close ( )
    • 关闭 socket。套接字对象上所有以后的操作都将失败。远端将不再接收任何数据(在清除排队的数据之后)。套接字在被垃圾回收时会自动关闭。

Note

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

  • socket. connect(地址)
    • 连接到位于* address 的远程套接字。 ( address *的格式取决于地址系列-参见上文.)

Note

从历史上看,此方法接受了AF_INET个地址的Pair参数,而不仅仅是一个 Tuples。这从来不是故意的,并且在 Python 2.0 和更高版本中不再可用。

  • socket. connect_ex(地址)
    • 类似于connect(address),但返回错误指示符而不是针对 C 级connect()调用返回的错误引发异常(其他问题,例如“找不到主机”仍然可以引发异常)。如果操作成功,错误指示符为0,否则为errno变量的值。这对于支持例如异步连接很有用。

Note

从历史上看,此方法接受了AF_INET个地址的Pair参数,而不仅仅是一个 Tuples。这从来不是故意的,并且在 Python 2.0 和更高版本中不再可用。

  • socket. fileno ( )
    • 返回套接字的文件 Descriptors(一个小整数)。这对select.select()很有用。

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

  • socket. getpeername ( )

    • 返回套接字连接到的远程地址。例如,这对于查找远程 IPv4/v6 套接字的端口号很有用。 (返回的地址格式取决于地址系列-参见上文.)在某些系统上,不支持此Function。
  • socket. getsockname ( )

    • 返回套接字自己的地址。例如,这对于查找 IPv4/v6 套接字的端口号很有用。 (返回的地址格式取决于地址系列-参见上文.)
  • socket. getsockopt(* level optname * [,* buflen *])

    • 返回给定套接字选项的值(请参见 Unix 手册页* getsockopt(2))。在此模块中定义了所需的符号常量(SO_*等)。如果不存在 buflen ,则假定使用整数选项,并且该整数值由函数返回。如果存在 buflen *,则它指定用于接收选项的缓冲区的最大长度,并且此缓冲区作为字符串返回。由调用者决定对缓冲区的内容进行解码(有关对编码为字符串的 C 结构进行解码的方法,请参见可选的内置模块struct)。
  • socket. ioctl(* control option *)

      • Platform

      • Windows

ioctl()方法是 WSAIoctl 系统接口的受限接口。有关更多信息,请参考Win32 documentation

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

2.6 版的新Function。

  • socket. listen(积压)

    • 侦听与套接字的连接。 * backlog *参数指定排队连接的最大数量,并且至少应为 0;最大值取决于系统(通常为 5),最小值强制为 0.
  • socket. makefile([* mode * [,* bufsize *]])

    • 返回与套接字关联的* file 对象*。 (文件对象在File Objects中描述。)文件对象在调用其close()方法时不会显式关闭套接字,而只会删除其对套接字对象的引用,因此,如果未从其他任何地方引用该套接字,则该套接字将被关闭。 。

套接字必须处于阻止模式(不能有超时)。可选的* mode bufsize *参数的解释方式与内置file()函数的解释方式相同。

Note

在 Windows 上,不能在期望带有文件 Descriptors 的文件对象(例如subprocess.Popen()的流参数)使用makefile()创建的类似文件的对象。

  • socket. recv(* bufsize * [,* flags *])
    • 从套接字接收数据。返回值是代表接收到的数据的字符串。一次可接收的最大数据量由* bufsize 指定。有关可选参数 flags 的含义,请参见 Unix 手册页 recv(2)*;它默认为零。

Note

为了与硬件和网络的实际情况达到最佳匹配,* bufsize *的值应为 2 的相对较小的幂,例如 4096.

  • socket. recvfrom(* bufsize * [,* flags *])

    • 从套接字接收数据。返回值是Pair(string, address),其中* string 是表示接收到的数据的字符串,而 address 是发送数据的套接字的地址。有关可选参数 flags 的含义,请参见 Unix 手册页 recv(2);它默认为零。 ( address *的格式取决于地址系列-参见上文.)
  • socket. recvfrom_into(* buffer * [,* nbytes * [,* flags *]])

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

2.5 版的新Function。

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

2.5 版的新Function。

  • socket. send(* string * [,* flags *])

    • 将数据发送到套接字。该套接字必须连接到远程套接字。可选的* flags 参数与上面的recv()具有相同的含义。返回发送的字节数。应用程序负责检查所有数据是否已发送;如果仅传输了一些数据,则应用程序需要try传送其余数据。有关此概念的更多信息,请咨询套接字编程方法
  • socket. sendall(* string * [,* flags *])

    • 将数据发送到套接字。该套接字必须连接到远程套接字。可选的* flags 参数与上面的recv()具有相同的含义。与send()不同,此方法 continue 从* string *发送数据,直到所有数据都已发送或发生错误为止。 None成功返回。如果出错,则会引发异常,并且无法确定成功发送了多少数据(如果有)。
  • socket. sendto(* string address *)

  • socket. sendto(* string flags address *)

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

    • 设置套接字的阻止或非阻止模式:如果* flag *为 0,则将套接字设置为非阻止,否则设置为阻止模式。最初,所有套接字都处于阻塞模式。在非阻塞模式下,如果recv()调用未找到任何数据,或者send()调用无法立即处理数据,则会引发error异常;否则,将引发error异常。在阻塞模式下,呼叫将阻塞直到可以 continue 进行。 s.setblocking(0)等效于s.settimeout(0.0); s.setblocking(1)等效于s.settimeout(None)
  • socket. settimeout(* value *)

    • 在阻止套接字操作上设置超时。 * value 参数可以是表示秒的非负浮点数,也可以是None。如果给出了浮点数,则在操作完成之前,如果超时时间 value *已经过去,则后续的套接字操作将引发timeout异常。将超时设置为None会禁用套接字操作的超时。 s.settimeout(0.0)等效于s.setblocking(0); s.settimeout(None)等效于s.setblocking(1)

2.3 版的新Function。

  • socket. gettimeout ( )
    • 返回与套接字操作关联的超时(以秒为单位)(浮点数);如果未设置超时,则返回None。这反映了对setblocking()settimeout()的最后一次呼叫。

2.3 版的新Function。

有关套接字阻塞和超时的一些注意事项:套接字对象可以处于以下三种模式之一:阻塞,非阻塞或超时。套接字始终以阻止模式创建。在阻止模式下,操作将阻止直到完成或系统返回错误(例如连接超时)。在非阻塞模式下,如果操作无法立即完成,则操作将失败(不幸的是,错误取决于系统)。在超时模式下,如果无法在为套接字指定的超时时间内完成操作,或者系统返回错误,则操作将失败。 setblocking()方法只是某些settimeout()调用的简写。

超时模式在内部将套接字设置为非阻塞模式。阻塞和超时模式在引用相同网络端点的文件 Descriptors 和套接字对象之间共享。结果是,仅当套接字处于阻塞模式时才可以使用makefile()方法返回的文件对象。在超时或非阻塞模式下无法立即完成的文件操作将失败。

请注意,connect()操作受超时设置的约束,通常建议在调用connect()之前将settimeout()调用或将超时参数传递给create_connection()。无论任何 Python 套接字超时设置如何,系统网络堆栈都可能返回其自身的连接超时错误。

  • socket. setsockopt(* level optname value *)
    • 设置给定套接字选项的值(请参见 Unix 手册页* setsockopt(2)*)。所需的符号常量在socket模块(SO_*等)中定义。该值可以是整数,也可以是表示缓冲区的字符串。在后一种情况下,由调用方确保字符串包含正确的位(有关将 C 结构编码为字符串的方法,请参见可选的内置模块struct)。
  • socket. shutdown(如何)
    • 关闭连接的一半或一半。如果* how SHUT_RD,则不允许进一步接收。如果 how SHUT_WR,则不允许进一步发送。如果 how *是SHUT_RDWR,则不允许进一步发送和接收。根据平台的不同,关闭一半连接也可以关闭另一半(例如,在 Mac OS X 上,shutdown(SHUT_WR)不允许在连接的另一端进行进一步读取)。

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

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

  • socket. family
    • 套接字家族。

2.5 版的新Function。

  • socket. type
    • 套接字类型。

2.5 版的新Function。

  • socket. proto
    • 套接字协议。

2.5 版的新Function。

17.2.2. Example

这是使用 TCP/IP 协议的四个最小示例程序:一台服务器,该服务器回显它收到的所有数据(仅为一个 Client 端提供服务),以及一个使用它的 Client 端。请注意,服务器必须执行 Sequencessocket()bind()listen()accept()(可能重复accept()以为多个 Client 端提供服务),而 Client 端仅需要 Sequencessocket()connect()。还要注意,服务器不在正在侦听的套接字上sendall()/recv(),而是在accept()返回的新套接字上。

前两个示例仅支持 IPv4.

# Echo server program
import socket

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

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

接下来的两个示例与以上两个示例相同,但同时支持 IPv4 和 IPv6.服务器端将监听第一个可用的地址族(它应该监听两个)。在大多数支持 IPv6 的系统上,IPv6 优先,并且服务器可能不接受 IPv4 流量。Client 端将try连接到由于名称解析而返回的所有地址,并将流量发送到成功连接的第一个地址。

# 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 socket.error as msg:
        s = None
        continue
    try:
        s.bind(sa)
        s.listen(1)
    except socket.error as msg:
        s.close()
        s = None
        continue
    break
if s is None:
    print 'could not open socket'
    sys.exit(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
    data = conn.recv(1024)
    if not data: break
    conn.send(data)
conn.close()
# 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 socket.error as msg:
        s = None
        continue
    try:
        s.connect(sa)
    except socket.error as msg:
        s.close()
        s = None
        continue
    break
if s is None:
    print 'could not open socket'
    sys.exit(1)
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)

最后一个示例显示了如何在 Windows 上使用原始套接字编写一个非常简单的网络嗅探器。该示例需要 Management 员特权才能修改接口:

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)

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

socket.error: [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状态的本地套接字,而不必 await 其自然超时到期。