17.2. socket底层网络接口

此模块提供了对 BSD socket 接口的支持。它可以在所有主流的Unix系统 , Windows , Mac OS X , BeOS , OS/2 以及其他可支持的平台上运行。

注意

一些功能可能依赖于系统平台本身,例如对系统 socket API 函数的调用。

想要了解Socket程序的知识(基于C语言),请参照以下文档:Stuart Sechrest写的《An Introductory 4.3BSD Interprocess Communication Tutorial》,Samuel J. Leffler写的《An Advanced 4.3BSD Interprocess Communication Tutorial》等等。这两篇文档都可以在UNIX Programmer’s Manual与Supplementary Documents 1 (sections PS1:7 and PS1:8)中找到。系统平台中针对各式Socket类系统调用的参考说明也是很重要的Socket语法资料。在Linux中叫做 manual pages , 在 Windows 中可以参考 WinSock(或者 Winsock2)规范。如果想用 IPv6 的 API,请参照《RFC 3493》——Basic Socket Interface Extensions for IPv6。

Python 的接口是对 Unix 系统调用与 Socket 函数的库接口函数的直译,非常易于上手,例如:函数 socket() 返回一个 socket object 套接字对象,该对象的方法实现了各式各样的系统套接字调用函数。 参数类型比 C 语言稍微高级一些,例如:当我们在 Python 文本里使用 read()write() 收到操作信号时缓存分配是自动进行的,并且缓冲区大小跟发送操作信号时是一样的。

关于 Socket 中定义地址的规则如下:单一字符串用于AF_UNIX 地址簇,字符串对(host, port)用于AF_INET 地址簇,其中 host 是描述主机名与互联网域名(如 'daring.cwi.nl')或者可以是一个IPv4的地址(如'100.50.200.5'),而 port是一个整数。For AF_INET6 address family, a four-tuple (host, port, flowinfo, scopeid) is used, where flowinfo and scopeid represents sin6_flowinfo and sin6_scope_id member in struct sockaddr_in6 in C. For socket module methods, flowinfo and scopeid can be omitted just for backward compatibility. 注意,尽管如此,省略scopeid参数会在操作有范围限定的 IPv6 地址时出现问题。目前尚不支持其他地址簇。The address format required by a particular socket object is automatically selected based on the address family specified when the socket object was created.

For IPv4 addresses, two special forms are accepted instead of a host address: the empty string represents INADDR_ANY, and the string '<broadcast>' represents INADDR_BROADCAST. The behavior is not available for IPv6 for backward compatibility, therefore, you may want to avoid these if you intend to support IPv6 with your Python programs.

If you use a hostname in the host portion of IPv4/v6 socket address, the program may show a nondeterministic behavior, as Python uses the first address returned from the DNS resolution. The socket address will be resolved differently into an actual IPv4/v6 address, depending on the results from DNS resolution and/or the host configuration. For deterministic behavior use a numeric address in host portion.

New in version 2.5: AF_NETLINK sockets 被设计为一对值:pid, groups.

New in version 2.6: Linux-only support for TIPC is also available using the AF_TIPC address family. TIPC是一种开放的且不基于IP的网络通信协议,协议本身是被设计为用于集群计算机环境。Addresses are represented by a tuple, and the fields depend on the address type. The general tuple form is (addr_type, v1, v2, v3 [, scope]), where:

  • addr_typeTIPC_ADDR_NAMESEQTIPC_ADDR_NAME,或者TIPC_ADDR_ID三者之一;

  • scopeTIPC_ZONE_SCOPETIPC_CLUSTER_SCOPE,和 TIPC_NODE_SCOPE三者之一;

  • addr_typeTIPC_ADDR_NAME,那么v1  就是服务器类型, v2 就是端口识别号, and v3必须为0。

    addr_typeTIPC_ADDR_NAMESEQ,那么v1 就是服务器类型v2就是低位端口号,并且v3就是高位端口号。

    addr_typeTIPC_ADDR_ID那么v1就是节点,v2就是参考,并且 v3 必须被设为0..

所有的错误都会抛出异常, 常见的异常都是由非法的参数类型与内存溢出引发的;由socket或者由地址语法引发的error属于socket.error.

通过 setblocking() 可以实现非阻塞模式。但实现这个的前提是在 settimeout() 中设置了超时。

socket 模块提供了以下的常量与函数:

exception socket.error

这个异常由socket related errors引发, 伴随产生的信息会有一个字符串告诉我们什么东西出错了,同时会用一个元组(errno, string)来返回系统调用中导致的错误,与os.error的返回结果类似。可以查看errno模块的相关信息,这个模块包含由操作系统底层定义的error code的名字。

2.6版本中的调整:socket.error 现在是 IOError 类的子类了。

exception socket.herror

这个异常由 address-related errors导致,也就是说由使用h_errno的C API函数导致,包括gethostbyname_ex()gethostbyaddr()

产生的返回值是一个通过调用library库返回的描述错误的元组 (h_errno, string)例如由C函数hstrerror() 返回用于描述h_errno字符串

exception socket.gaierror

这个异常由 address-related errors 导致,来源于 getaddrinfo()getnameinfo()产生的返回值是一个通过调用library返回的描述错误的元组(error, string)其中的 string 是对 error 的描述,就如同 C 函数 gai_strerror() 的返回值一样。error值会匹配此模块预定义的EAI_*常数之一

exception socket.timeout

当通过主调用settimeout()开启某个socket连接的超时选项后,如果这个连接产生了超时行为,那么这个exception就会被引发。所产生的值通常就是很精确的“timed out”字符串。

2.3版本新特性。

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 的类型,用于 socket() 函数的第二个参数。(只有SOCK_STREAMSOCK_DGRAM 较为常用)

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

这里有很多常量,这些在Unix的sockets和/或IP协议文档里大多都可以找到,而这些在我们这个socket模块中也有定义。他们通常作为参数用于setsockopt()getsockopt() 这两个socket对象方法。大多数情况下,只有那些符号在Unix预定于头文件中有定义;而对于少部分的符号,推荐使用默认值

SIO_*
RCVALL_*

Symbolic name meaning all available interfaces这些常量用作套接字对象的ioctl()方法的参数。

New in version 2.6.

TIPC_*

TIPC相关常数,匹配由C socket API导出的常量。有关更多信息,请参阅TIPC文档。

New in version 2.6.

socket.has_ipv6

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

New in version 2.3.

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

连接到互联网上的TCP服务地址(一个2元组(主机, 端口)),并返回套接字对象。这是比socket.connect()更高级别的功能:如果主机是一个非数字主机名,它将尝试解析它AF_INET AF_INET6,然后尝试依次连接所有可能的地址,直到连接成功。这样可以轻松地编写兼容IPv4和IPv6的客户端。

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

If supplied, source_address must be a 2-tuple (host, port) for the socket to bind to as its source address before connecting. 如果主机或端口分别为“或”,则将使用OS默认行为。

New in version 2.6.

Changed in version 2.7: source_address已添加。

socket.getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]])

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

可以可选地指定familysocktypeproto参数,以缩小返回的地址列表。默认情况下,它们的值为0,这意味着选择了完整的结果范围。标志参数可以是一个或几个AI _ *常量,并将影响如何计算和返回结果。Its default value is 0. 例如,AI_NUMERICHOST将禁用域名解析,如果主机是域名,则会引发错误。

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

(family, socktype, proto, canonname, sockaddr)

In these tuples, family, socktype, proto are all integers and are meant to be passed to the socket() function. 如果AI_CANONNAME标志参数的一部分,canonname将是表示主机的规范名称的字符串;else canonname will be empty. 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上提取到www.python.org的假设TCP连接的地址信息(如果未启用IPv6,则系统上的结果可能会有所不同):

>>> socket.getaddrinfo("www.python.org", 80, 0, 0, socket.SOL_TCP)
[(2, 1, 6, '', ('82.94.164.162', 80)),
 (10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]

New in version 2.2.

socket.getfqdn([name])

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

New in version 2.0.

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() does not support IPv6 name resolution, and getaddrinfo() should be used instead for IPv4/v6 dual stack support.

socket.gethostname()

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

如果您想知道当前机器的IP地址,可能需要使用gethostbyname(gethostname())此操作假定主机有一个有效的地址对主机映射,并且该假设并不总是保持。

注意:gethostname()并不总是返回完全限定的域名;use getfqdn() (see above).

socket.gethostbyaddr(ip_address)

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

socket.getnameinfo(sockaddr, flags)

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

新版本在2.2中发布.

socket.getprotobyname(protocolname)

第三个参数的 socket()功能(可选):翻译互联网协议名称(例如'icmp')为一个适合传递的常数。 通常只需要在“raw”模式(SOCK_RAW)中打开套接字;对于正常的套接字模式,如果协议被省略或为零,则自动选择正确的协议。

socket.getservbyname(servicename[, protocolname])

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

socket.getservbyport(port[, protocolname])

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

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

使用给定的地址族,套接字类型和协议号创建一个新的套接字。The address family should be AF_INET (the default), AF_INET6 or AF_UNIX. 套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM或其他SOCK _常量之一。协议号通常为零,在这种情况下可以省略。

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

使用给定的地址族,套接字类型和协议号构建一对连接的套接字对象。地址族,套接字类型和协议号与上述socket()功能一样。如果在平台上定义,默认系列为AF_UNIXotherwise, the default is AF_INET. Availability: Unix.

New in version 2.4.

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

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

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的对象进行对话时,这是有用的,这是C类型的这个函数返回32位打包二进制。

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

如果传递给此函数的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的对象进行对话时,这是有用的,这是C类型的32位打包的二进制数据这个函数作为参数。

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

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无效,则将引发socket.error请注意,正是有效的取决于address_family的值和inet_pton()的底层实现。

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

New in version 2.3.

socket.inet_ntop(address_family, packed_ip)

Convert a packed IP address (a string of some number of characters) to its standard, family-specific string representation (for example, '7.10.0.5' or '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()的调用引发了错误的socket.error

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

New in version 2.3.

socket.getdefaulttimeout()

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

New in version 2.3.

socket.setdefaulttimeout(timeout)

为新的套接字对象设置默认超时(以秒为单位)(float)。None表示新的套接字对象没有超时。socket模块刚导入时,默认值为None

New in version 2.3.

socket.SocketType

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

See also

Module SocketServer
Classes that simplify writing network servers.
Module ssl
A TLS/SSL wrapper for socket objects.

17.2.1. Socket 对象

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

socket.accept()

接受连接。套接字必须绑定到一个地址并侦听连接。The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.

socket.bind(address)

将套接字绑定到地址套接字不能被绑定。地址的格式取决于地址族 - 请参见上文。)

Note

此方法历来已经接受了一个AF_INET地址而不是一个元组的参数。这并不是有意的,在Python 2.0和更高版本中不再可用。

socket.close()

关闭插座。套接字对象上的所有未来操作将失败。远程端将不再接收数据(排队数据刷新后)。当垃圾收集时,套接字将自动关闭。

Note

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

socket.connect(address)

连接到地址上的远程套接字。地址的格式取决于地址族 - 请参见上文。)

Note

此方法历来已经接受了一个AF_INET地址而不是一个元组的参数。这并不是有意的,在Python 2.0和更高版本中不再可用。

socket.connect_ex(address)

Like connect(address), but return an error indicator instead of raising an exception for errors returned by the C-level connect() call (other problems, such as “host not found,” can still raise exceptions). 如果操作成功,则错误指示符为0,否则为errno变量的值。这对于支持例如异步连接是有用的。

Note

此方法历来已经接受了一个AF_INET地址而不是一个元组的参数。这并不是有意的,在Python 2.0和更高版本中不再可用。

socket.fileno()

返回套接字的文件描述符(一个小整数)。这对于select.select()是有用的。

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

socket.getpeername()

返回与其连接的远程地址。例如,这可以找出远程IPv4 / v6套接字的端口号。(返回地址的格式取决于地址族 - 请参见上文。)在某些系统上,不支持此功能。

socket.getsockname()

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

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

返回给定套接字选项的值(请参阅Unix手册页getsockopt(2))。The needed symbolic constants (SO_* etc.) are defined in this module. 如果buflen不存在,则假定整数选项,并且该函数返回其整数值。如果存在buflen,则它指定用于接收选项的缓冲区的最大长度,该缓冲区以字符串形式返回。调用者解码缓冲区的内容(请参阅可选的内置模块struct来解码编码为字符串的C结构)。

socket.ioctl(control, option)
Platform :Windows

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

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

New in version 2.6.

socket.listen(backlog)

监听到插座的连接。backlog参数指定排队连接的最大数量,并且应至少为0;最大值取决于系统(通常为5),最小值被强制为0。

socket.makefile([mode[, bufsize]])

返回与套接字关联的文件对象(文件对象在文件对象中描述。)文件对象引用套接字文件描述符的dup() ped版本,因此文件对象和套接字对象可能会被独立关闭或垃圾收集。套接字必须处于阻塞模式(不能超时)。可选的模式bufsize参数的解释方式与内置的file()函数相同。

Note

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

socket.recv(bufsize[, flags])

从套接字接收数据。返回值是表示接收到的数据的字符串。一次要接收的最大数据量由bufsize指定。See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

Note

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

socket.recvfrom(bufsize[, flags])

从套接字接收数据。The return value is a pair (string, address) where string is a string representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)

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

从套接字接收数据,将其写入缓冲区,而不是创建一个新的字符串。The return value is a pair (nbytes, address) where nbytes is the number of bytes received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)

New in version 2.5.

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

从套接字接收到nbytes个字节,将数据存储到缓冲区中,而不是创建一个新的字符串。如果未指定nbytes(或0),则接收到给定缓冲区中可用的大小。返回接收的字节数。See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

New in version 2.5.

socket.send(string[, flags])

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

socket.sendall(string[, flags])

发送数据到套接字。插座必须连接到远程插座。可选的标志参数与上述recv()的含义相同。send()不同,该方法继续从字符串发送数据,直到所有数据发送或发生错误为止。None is returned on success. 出错时,会出现异常,无法确定成功发送的数据(如果有)。

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

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

socket.setblocking(flag)

设置套接字的阻塞或非阻塞模式:如果标志为0,则套接字设置为非阻塞,否则为阻塞模式。最初所有套接字处于阻塞模式。在非阻塞模式下,如果recv()调用未找到任何数据,或者如果send()调用不能立即处理数据,则错误引发异常;在阻塞模式下,呼叫阻塞,直到它们可以继续。s.setblocking(0)等价于s.settimeout(0.0)s.setblocking(1)相当于s.settimeout(None)

socket.settimeout(value)

在阻塞套接字操作时设置一个超时。参数可以是表示秒或的非负数浮点数。如果给定了一个浮点数,则在操作完成之前,如果超时时间已经过去,后续的套接字操作将引发超时异常。设置超时禁用套接字操作超时。s.settimeout(0.0)相当于s.setblocking(0)s.settimeout(None)相当于s.setblocking(1)

New in version 2.3.

socket.gettimeout()

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

New in version 2.3.

一些关于套接字阻塞和超时的注释:套接字对象可以是以下三种模式之一:阻塞,非阻塞或超时。套接字始终以阻止模式创建。在阻塞模式下,操作阻塞直到完成或系统返回错误(如连接超时)。在非阻塞模式下,如果不能立即完成操作,则操作失败(错误不幸与系统相关)。在超时模式下,如果在为套接字指定的超时时间内无法完成操作或系统返回错误,则操作将失败。The setblocking() method is simply a shorthand for certain settimeout() calls.

超时模式将套接字内部设置为非阻塞模式。阻塞和超时模式在引用同一网络端点的文件描述符和套接字对象之间共享。这样做的结果是,只有当套接字处于阻塞模式时,才能使用makefile()方法返回的文件对象;在超时或非阻塞模式下,无法立即完成的文件操作将失败。

Note that the connect() operation is 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套接字超时设置,系统网络堆栈都可能返回自身的连接超时错误。

socket.setsockopt(level, optname, value)

设置给定套接字选项的值(请参阅Unix手册页setsockopt(2))。所需的符号常量在套接字模块(SO _ *等)中定义。该值可以是表示缓冲区的整数或字符串。在后一种情况下,由调用方确定字符串包含适当的位(请参阅可选的内置模块struct,以将C结构编码为字符串)。

socket.shutdown(how)

关闭一边或两边的连接。如果 howSHUT_RD,断开远程接收。如果 howSHUT_WR,断开远程发送。如果howSHUT_RDWR, 断开远程接收和发送。取决于平台,关闭连接的一半也可以关闭相反的一半(例如在Mac OS X上,shutdown(SHUT_WR)不允许在连接的另一端进一步读取)。

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

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

socket.family

The socket family.

New in version 2.5.

socket.type

The socket type.

New in version 2.5.

socket.proto

The socket protocol.

New in version 2.5.

17.2.2. 例子

以下是使用TCP / IP协议的四个最小示例程序:一个服务器回显所有收到的数据(仅服务于一个客户端)和使用它的客户端。需要注意的是,服务器必须进行这些顺序操作来服务:socket(), bind(), listen(), accept() (如果不止一台客户端,可能需要重复 accept() ), 而客户端只需要进行以下序列的操作 socket(), connect().同时也需要注意服务器不会sendall()/recv() 在他正在listening的socket而是在新的通过accept()返回的socket上。

前两个示例仅支持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流量。客户端将尝试连接到由于名称解析返回的所有地址,并将流量发送到第一个连接成功。

# 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上使用原始套接字编写一个非常简单的网络嗅探器。该示例需要管理员权限才能修改界面:

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状态,并且不能立即重新使用。

There is a socket flag to set, in order to prevent this, 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))

the SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state, without waiting for its natural timeout to expire.