首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

socket

该模块提供对BSD 套接字接口的访问。它适用于所有现代Unix系统,Windows,Mac OS X,BeOS,OS / 2以及其他平台。

注意

某些行为可能与平台有关,因为调用操作系统套接字API。

有关套接字编程的介绍(使用C语言),请参见以下文章:Stuart Sechrest的“4.3BSD进程间通信教程简介”和Samuel J. Leffler等人的“高级4.3BSD进程间通信教程”,均在UNIX程序员手册,补充文件1(PS1:7和PS1:8章节)。各种与套接字相关的系统调用的特定于平台的参考材料也是关于套接字语义细节的宝贵信息来源。对于Unix,请参考手册页面; 对于Windows,请参阅WinSock(或Winsock 2)规范。对于IPv6就绪的API,读者可能想要参考标题为IPv6的基本套接字接口扩展的RFC 3493

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

套接字地址如下所示:单个字符串用于AF_UNIX地址系列。一对(host, port)用于AF_INET地址族,其中host是表示Internet域表示法中的主机名的字符串,例如像'daring.cwi.nl'IPv4地址'100.50.200.5',而port是整数。对于AF_INET6地址族,一个四元组(host, port, flowinfo, scopeid)被使用,其中flowinfoscopeid表示sin6_flowinfosin6_scope_id构件在struct sockaddr_in6中C.对于socket模块的方法,flowinfoscopeid只是为了向后兼容性可被省略。但请注意,省略了scopeid可能会导致操作范围内的IPv6地址时出现问题。其他地址系列目前不受支持。特定套接字对象所需的地址格式将根据套接字对象创建时指定的地址族自动选择。

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

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

2.5版本中的新功能:AF_NETLINK套接字表示为成对pid, groups

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

  • ADDR_TYPE是一个TIPC_ADDR_NAMESEQTIPC_ADDR_NAMETIPC_ADDR_ID
  • 范围是一个TIPC_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。

所有错误都会引发异常 可以引发无效参数类型和内存不足情况的正常例外; 与套接字或地址语义相关的错误会引发错误socket.error

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

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

exception socket.error

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

在版本2.6中更改:socket.error现在是一个子类IOError

exception socket.herror

这个异常是针对与地址相关的错误引发的,即在C API 中使用h_errno的函数,包括gethostbyname_ex()gethostbyaddr()

随附的值是(h_errno, string)表示由库调用返回的错误的对。字符串表示由C函数返回的h_errno的描述hstrerror()

exception socket.gaierror

对于getaddrinfo()和地址相关的错误,此例外引发getnameinfo()。随附的值是(error, string)表示由库调用返回的错误的对。字符串表示由C函数返回的错误描述gai_strerror()。该误差值将匹配的一个EAI_*在此模块中定义的常量。

exception socket.timeout

当通过先前的调用启用超时的套接字上发生超时时,会引发此异常settimeout()。随附的值是一个字符串,其值现在总是“超时”。

2.3版本的新功能。

socket.AF_UNIXsocket.AF_INETsocket.AF_INET6

这些常量表示用于第一个参数的地址(和协议)族socket()。如果AF_UNIX常量没有被定义,那么这个协议是不受支持的。

socket.SOCK_STREAMsocket.SOCK_DGRAMsocket.SOCK_RAWsocket.SOCK_RDMsocket.SOCK_SEQPACKET

这些常量表示用于第二个参数的套接字类型socket()。(仅SOCK_STREAMSOCK_DGRAM似乎是普遍有用的。)

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

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

SIO_*RCVALL_*

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

2.6版本中的新功能。

TIPC_*

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

2.6版本中的新功能。

socket.has_ipv6

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

2.3版本的新功能。

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

连接到监听Internet 地址(2元组(host, port))的TCP服务,然后返回套接字对象。这是一个更高层次的功能比socket.connect():如果主机是一个非数字的主机名,它会尽力解决两个AF_INETAF_INET6,然后尝试连接到所有可能的地址,直到有一个连接成功。这使得编写兼容IPv4和IPv6的客户端变得容易。

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

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

2.6版本中的新功能。

在版本2.7中更改:添加了source_address

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

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

家庭socktype参数可以以缩小返回的地址的列表中随意指定的。默认情况下,它们的值是0,表示选择了全部范围的结果。该标志参数可以是一个或几个的AI_*常数,会影响结果的方式计算并返回。它的默认值是0。例如,AI_NUMERICHOST将禁用域名解析并在主机是域名时引发错误。

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

(family, socktype, proto, canonname, sockaddr)

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

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

代码语言:javascript
复制
>>> 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版本中的新功能。

socket.getfqdn([name])

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

2.0版本中的新功能。

socket.gethostbyname(hostname)

将主机名转换为IPv4地址格式。IPv4地址以字符串形式返回,例如'100.50.200.5'。如果主机名称本身是IPv4地址,则它将保持不变。查看gethostbyname_ex()更完整的界面。gethostbyname()不支持IPv6名称解析,getaddrinfo()应该用于IPv4 / v6双栈支持。

socket.gethostbyname_ex(hostname)

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

socket.gethostname()

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

如果你想知道当前机器的IP地址,你可以使用gethostbyname(gethostname())。此操作假定主机有一个有效的地址到主机映射,并且该假设并不总是成立。

注意:gethostname()并不总是返回完全合格的域名; 使用getfqdn()(见上)。

socket.gethostbyaddr(ip_address)

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

socket.getnameinfo(sockaddr, flags)

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

2.2版本中的新功能。

socket.getprotobyname(protocolname)

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

socket.getservbyname(servicename[, protocolname])

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

socket.getservbyport(port[, protocolname])

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

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

使用给定的地址系列,套接字类型和协议号创建一个新套接字。地址族应该是AF_INET(默认),AF_INET6或者AF_UNIX。套接字类型应该是SOCK_STREAM(默认),SOCK_DGRAM或者可能是其他SOCK_常量之一。协议编号通常为零,在这种情况下可以省略。

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

使用给定的地址系列,套接字类型和协议编号构建一对连接的套接字对象。地址族,套接字类型和协议号与上述socket()功能一样。AF_UNIX如果在平台上定义了默认系列,否则,默认是AF_INET。可用性:Unix。

2.4版本中的新功能。

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

复制文件描述符fd(由文件对象的fileno()方法返回的整数),并根据结果构建一个套接字对象。地址族,套接字类型和协议号码与上述socket()功能相同。文件描述符应该引用一个套接字,但这不会被检查 - 如果文件描述符无效,对象的后续操作可能会失败。这个函数很少需要,但可以用来在传递给程序的套接字上获取或设置套接字选项作为标准输入或输出(例如由Unix inet守护进程启动的服务器)。假设套接字处于阻塞模式。可用性: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位打包二进制格式,作为长度为4个字符的字符串。在与使用标准C库的程序进行交谈并且需要类型对象时这很有用struct in_addr,该类型对于此函数返回的32位打包二进制文件的C类型。

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

如果传递给该函数的IPv4地址字符串无效,socket.error将会引发。请注意,究竟什么是有效的取决于底层的C实现inet_aton()

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

socket.inet_ntoa(packed_ip)

将32位打包的IPv4地址(一个长度为4个字符的字符串)转换为其标准的四角形字符串表示形式(例如“123.45.67.89”)。在与使用标准C库的程序进行交谈并且需要类型对象时这非常有用struct in_addr,该类型对象是该函数用作参数的32位打包二进制数据的C类型。

如果传递给这个函数的字符串长度不是4个字节,socket.error将会被提升。inet_ntoa()不支持IPv6,inet_ntop()应该用于IPv4 / v6双栈支持。

socket.inet_pton(address_family, ip_string)

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

address_family支持的值是当前AF_INETAF_INET6。如果IP地址字符串ip_string无效,socket.error则会引发。请注意,究竟什么是有效的取决于address_family的值和底层实现inet_pton()

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

2.3版本的新功能。

socket.inet_ntop(address_family, packed_ip)

当库或网络协议返回类型(类似于)或类型的对象时,将打包的IP地址(包含若干字符的字符串)转换为其标准的特定于家族的字符串表示形式(例如'7.10.0.5''5aef:2b::8'inet_ntop()是很有用的。struct in_addrinet_ntoa()struct in6_addr

address_family支持的值是当前AF_INETAF_INET6。如果字符串packed_ip不是指定地址系列的正确长度,ValueError将会引发。A socket.error从呼叫错误中引发inet_ntop()

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

2.3版本的新功能。

socket.getdefaulttimeout()

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

2.3版本的新功能。

socket.setdefaulttimeout(timeout)

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

2.3版本的新功能。

socket.SocketType

这是一个代表套接字对象类型的Python类型对象。它和type(socket(...))。一样。

1.套接字对象

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

socket.accept()

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

socket.bind(address)

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

注意

历史上这种方法接受了一对AF_INET地址参数,而不是只有一个元组。这从来都不是有意的,并且在Python 2.0及更高版本中不再可用。

socket.close()

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

注意

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

socket.connect(address)

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

注意

历史上这种方法接受了一对AF_INET地址参数,而不是只有一个元组。这从来都不是有意的,并且在Python 2.0及更高版本中不再可用。

socket.connect_ex(address)

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

注意

历史上这种方法接受了一对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))。所需的符号常量(SO_*等)在本模块中定义。如果buflen不存在,则假定整数选项,并且该函数返回其整数值。如果存在buflen,它指定用于接收选项的缓冲区的最大长度,并且该缓冲区作为字符串返回。这取决于调用者解码缓冲区的内容(请参阅可选的内置模块struct以解码编码为字符串的C结构)。

socket.ioctl(control, option)

Platform:

Windows

socket.listen(backlog)

听取与插座的连接。的积压参数指定排队的最大连接数和应至少为0; 最大值取决于系统(通常为5),最小值被强制为0。

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

返回与套接字关联的文件对象。(文件对象在文件对象中描述。)文件对象在其close()方法被调用时并没有明确地关闭套接字,但是只移除了它对套接字对象的引用,所以如果没有从其他地方引用它,套接字将被关闭。

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

注意

在Windows上,makefile()不能在具有文件描述符的文件对象所在的位置使用由此创建的类文件对象,例如subprocess.Popen()

socket.recv(bufsize[, flags])

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

注意

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

socket.recvfrom(bufsize[, flags])

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

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

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

2.5版本中的新功能。

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

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

2.5版本中的新功能。

socket.send(string[, flags])

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

socket.sendall(string[, flags])

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

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

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

socket.setblocking(flag)

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

socket.settimeout(value)

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

2.3版本的新功能。

socket.gettimeout()

返回与套接字操作相关的超时秒数(浮点数),或者None没有设置超时时间。这反映了最后一次呼叫setblocking()settimeout()

2.3版本的新功能。

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

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

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

socket.setsockopt(level, optname, value)

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

socket.shutdown(how)

关闭一个或两个连接的一半。如果怎么SHUT_RD,还接收被禁止。如果怎么SHUT_WR,进一步将是不允许的。如果怎么SHUT_RDWR,进一步的发送和接收被禁止。取决于平台,关闭连接的一半还可以关闭另一半(例如,在Mac OS X上,shutdown(SHUT_WR)不允许在连接的另一端进一步读取)。

请注意,没有方法read()write(); 使用recv()send()没有标志的说法来代替。

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

socket.family

套接字系列。

2.5版本中的新功能。

socket.type

套接字类型。

2.5版本中的新功能。

socket.proto

套接字协议。

2.5版本中的新功能。

2.例子

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

前两个示例仅支持IPv4。

代码语言:javascript
复制
# 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()
代码语言:javascript
复制
# 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流量。客户端将尝试连接到由于名称解析而返回的所有地址,并将流量发送到第一个成功连接的地址。

代码语言:javascript
复制
# 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()
代码语言:javascript
复制
# 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上使用原始套接字编写一个非常简单的网络嗅探器。该示例需要管理员权限来修改接口:

代码语言:javascript
复制
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)

在执行过程中执行多次延迟太小的示例可能会导致此错误:

代码语言:javascript
复制
socket.error: [Errno 98] Address already in use

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

有一个socket标志设置,以防止这一点,socket.SO_REUSEADDR

代码语言:javascript
复制
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状态中重用本地套接字,而不等待其自然超时过期。

扫码关注腾讯云开发者

领取腾讯云代金券