socket --- 底層網(wǎng)絡(luò)接口?

源代碼: Lib/socket.py


這個(gè)模塊提供了訪問BSD*套接字*的接口。在所有現(xiàn)代Unix系統(tǒng)、Windows、macOS和其他一些平臺(tái)上可用。

注解

一些行為可能因平臺(tái)不同而異,因?yàn)檎{(diào)用的是操作系統(tǒng)的套接字API。

這個(gè)Python接口是用Python的面向?qū)ο箫L(fēng)格對(duì)Unix系統(tǒng)調(diào)用和套接字庫接口的直譯:函數(shù) socket() 返回一個(gè) 套接字對(duì)象 ,其方法是對(duì)各種套接字系統(tǒng)調(diào)用的實(shí)現(xiàn)。形參類型一般與C接口相比更高級(jí):例如在Python文件 read()write()?操作中,接收操作的緩沖區(qū)分配是自動(dòng)的,發(fā)送操作的緩沖區(qū)長(zhǎng)度是隱式的。

參見

模塊 socketserver

用于簡(jiǎn)化網(wǎng)絡(luò)服務(wù)端編寫的類。

模塊 ssl

套接字對(duì)象的TLS/SSL封裝。

套接字協(xié)議族?

根據(jù)系統(tǒng)以及構(gòu)建選項(xiàng),此模塊提供了各種 socket 協(xié)議簇。

特定的 socket 對(duì)象需要的地址格式將根據(jù)此 socket 對(duì)象被創(chuàng)建時(shí)指定的地址族被自動(dòng)選擇。socket 地址表示如下:

  • 一個(gè)綁定在文件系統(tǒng)節(jié)點(diǎn)上的 AF_UNIX 套接字的地址表示為一個(gè)字符串,使用文件系統(tǒng)字符編碼和 'surrogateescape' 錯(cuò)誤回調(diào)方法(see PEP 383)。一個(gè)地址在 Linux 的抽象命名空間被返回為帶有初始的 null 字節(jié)的 bytes-like object ;注意在這個(gè)命名空間種的套接字可能與普通文件系統(tǒng)套接字通信,所以打算運(yùn)行在 Linux 上的程序可能需要解決兩種地址類型。當(dāng)傳遞為參數(shù)時(shí),一個(gè)字符串或字節(jié)類對(duì)象可以用于任一類型的地址。

    在 3.3 版更改: 以前,AF_UNIX 套接字路徑被假設(shè)使用 UTF-8 編碼。

    在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對(duì)象

  • 一對(duì) (host, port) 被用于 AF_INET 地址族,host 是一個(gè)代表互聯(lián)網(wǎng)域名表示法之內(nèi)主機(jī)名或者一個(gè) IPv4 地址的字符串,例如 'daring.cwi.nl''100.50.200.5'port 是一個(gè)整數(shù)。

    • 對(duì)于 IPv4 地址,有兩種可接受的特殊形式被用來代替一個(gè)主機(jī)地址: '' 代表 INADDR_ANY,用來綁定到所有接口;字符串 '<broadcast>' 代表 INADDR_BROADCAST。此行為不兼容 IPv6,因此,如果你的 Python 程序打算支持 IPv6,則可能需要避開這些。

  • 對(duì)于 AF_INET6 地址族,使用一個(gè)四元組 (host, port, flowinfo, scopeid)flowinfoscopeid 代表了 C 庫里 struct sockaddr_in6 中的 sin6_flowinfosin6_scope_id 成員。 對(duì)于 socket 模塊中的方法, flowinfoscopeid 可以被省略,只為了向后兼容。注意,scopeid 的省略可能會(huì)導(dǎo)致 IPv6 地址的操作范圍問題。

    在 3.7 版更改: 對(duì)于多播地址(其 scopeid 是有意義的),地址 可能不包含 %scope``(或 ``zone id)部分。該信息是多余的,可以放心省略(推薦)。

  • AF_NETLINK 套接字由一對(duì) (pid, groups) 表示。

  • 指定 AF_TIPC 地址族可以使用僅 Linux 支持的 TIPC 協(xié)議。TIPC 是一種開放的、非基于 IP 的網(wǎng)絡(luò)協(xié)議,旨在用于集群計(jì)算環(huán)境。其地址用元組表示,其中的字段取決于地址類型。一般元組形式為 (addr_type, v1, v2, v3 [, scope]),其中:

    • addr_typeTIPC_ADDR_NAMESEQTIPC_ADDR_NAMETIPC_ADDR_ID 中的一個(gè)。

    • scopeTIPC_ZONE_SCOPETIPC_CLUSTER_SCOPETIPC_NODE_SCOPE 中的一個(gè)。

    • 如果 addr_typeTIPC_ADDR_NAME,那么 v1 是服務(wù)器類型,v2 是端口標(biāo)識(shí)符,v3 應(yīng)為 0。

      如果 addr_typeTIPC_ADDR_NAMESEQ,那么 v1 是服務(wù)器類型,v2 是端口號(hào)下限,而 v3 是端口號(hào)上限。

      如果 addr_typeTIPC_ADDR_ID,那么 v1 是節(jié)點(diǎn) (node),v2 是 ref,v3 應(yīng)為 0。

  • AF_CAN 地址族使用元組 (interface, ),其中 interface 是表示網(wǎng)絡(luò)接口名稱的字符串,如 'can0'。網(wǎng)絡(luò)接口名 '' 可以用于接收本族所有網(wǎng)絡(luò)接口的數(shù)據(jù)包。

    • CAN_ISOTP 協(xié)議接受一個(gè)元組 (interface, rx_addr, tx_addr),其中兩個(gè)額外參數(shù)都是無符號(hào)長(zhǎng)整數(shù),都表示 CAN 標(biāo)識(shí)符(標(biāo)準(zhǔn)或擴(kuò)展標(biāo)識(shí)符)。

  • PF_SYSTEM 協(xié)議簇的 SYSPROTO_CONTROL 協(xié)議接受一個(gè)字符串或元組 (id, unit)。其中字符串是內(nèi)核控件的名稱,該控件使用動(dòng)態(tài)分配的 ID。而如果 ID 和內(nèi)核控件的單元 (unit) 編號(hào)都已知,或使用了已注冊(cè)的 ID,可以采用元組。

    3.3 新版功能.

  • AF_BLUETOOTH 支持以下協(xié)議和地址格式:

    • BTPROTO_L2CAP 接受 (bdaddr, psm),其中 bdaddr 為字符串格式的藍(lán)牙地址,psm 是一個(gè)整數(shù)。

    • BTPROTO_RFCOMM 接受 (bdaddr, channel),其中 bdaddr 為字符串格式的藍(lán)牙地址,channel 是一個(gè)整數(shù)。

    • BTPROTO_HCI 接受 (device_id,),其中 device_id 為整數(shù)或字符串,它表示接口對(duì)應(yīng)的藍(lán)牙地址(具體取決于你的系統(tǒng),NetBSD 和 DragonFlyBSD 需要藍(lán)牙地址字符串,其他系統(tǒng)需要整數(shù))。

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

    • BTPROTO_SCO 接受 bdaddr,其中 bdaddrbytes 對(duì)象,其中含有字符串格式的藍(lán)牙地址(如 b'12:23:34:45:56:67' ),F(xiàn)reeBSD 不支持此協(xié)議。

  • AF_ALG 是一個(gè)僅 Linux 可用的、基于套接字的接口,用于連接內(nèi)核加密算法。算法套接字可用包括 2 至 4 個(gè)元素的元組來配置 (type, name [, feat [, mask]]),其中:

    • type 是表示算法類型的字符串,如 aeadhashskcipherrng

    • name 是表示算法類型和操作模式的字符串,如 sha256hmac(sha256)cbc(aes)drbg_nopr_ctr_aes256

    • featmask 是無符號(hào) 32 位整數(shù)。

    Availability: Linux 2.6.38, some algorithm types require more recent Kernels.

    3.6 新版功能.

  • AF_VSOCK 用于支持虛擬機(jī)與宿主機(jī)之間的通訊。該套接字用 (CID, port) 元組表示,其中 Context ID (CID) 和 port 都是整數(shù)。

    Availability: Linux >= 4.8 QEMU >= 2.8 ESX >= 4.0 ESX Workstation >= 6.5.

    3.7 新版功能.

  • AF_PACKET 是一個(gè)底層接口,直接連接至網(wǎng)卡。數(shù)據(jù)包使用元組 (ifname, proto[, pkttype[, hatype[, addr]]]) 表示,其中:

    • ifname - 指定設(shè)備名稱的字符串。

    • proto - 一個(gè)用網(wǎng)絡(luò)字節(jié)序表示的整數(shù),指定以太網(wǎng)協(xié)議版本號(hào)。

    • pkttype - 指定數(shù)據(jù)包類型的整數(shù)(可選):

      • PACKET_HOST (默認(rèn)) - 數(shù)據(jù)包尋址到本地宿主機(jī)。

      • PACKET_BROADCAST - 物理層廣播報(bào)文。

      • PACKET_MULTIHOST - 數(shù)據(jù)包發(fā)送到物理層多播地址。

      • PACKET_OTHERHOST - 被(處于混雜模式的)網(wǎng)卡驅(qū)動(dòng)捕獲的、發(fā)送到其他主機(jī)的數(shù)據(jù)包。

      • PACKET_OUTGOING - 來自本地主機(jī)的、回環(huán)到一個(gè)套接字的數(shù)據(jù)包。

    • hatype - 可選整數(shù),指定 ARP 硬件地址類型。

    • addr - 可選的類字節(jié)串對(duì)象,用于指定硬件物理地址,其解釋取決于各設(shè)備。

如果你在 IPv4/v6 套接字地址的 host 部分中使用了一個(gè)主機(jī)名,此程序可能會(huì)表現(xiàn)不確定行為,因?yàn)?Python 使用 DNS 解析返回的第一個(gè)地址。套接字地址在實(shí)際的 IPv4/v6 中以不同方式解析,根據(jù) DNS 解析和/或 host 配置。為了確定行為,在 host 部分中使用數(shù)字地址。

所有的錯(cuò)誤都拋出異常。對(duì)于無效參數(shù)類型和內(nèi)存溢出異常情況可能拋出普通異常;從 Python 3.3 開始,與套接字或地址語義有關(guān)的錯(cuò)誤拋出 OSError 或它的子類之一(常用 socket.error)。

可以用 setblocking() 設(shè)置非阻塞模式。一個(gè)基于超時(shí)的 generalization 通過 settimeout() 支持。

模塊內(nèi)容?

socket 模塊導(dǎo)出以下元素。

異常?

exception socket.error?

一個(gè)被棄用的 OSError 的別名。

在 3.3 版更改: 根據(jù) PEP 3151,這個(gè)類是 OSError 的別名。

exception socket.herror?

OSError 的子類,本異常通常表示與地址相關(guān)的錯(cuò)誤,比如那些在 POSIX C API 中使用了 h_errno 的函數(shù),包括 gethostbyname_ex()gethostbyaddr()。附帶的值是一對(duì) (h_errno, string),代表庫調(diào)用返回的錯(cuò)誤。h_errno 是一個(gè)數(shù)字,而 string 表示 h_errno 的描述,它們由 C 函數(shù) hstrerror() 返回。

在 3.3 版更改: 此類是 OSError 的子類。

exception socket.gaierror?

OSError 的子類,本異常來自 getaddrinfo()getnameinfo(),表示與地址相關(guān)的錯(cuò)誤。附帶的值是一對(duì) (error, string),代表庫調(diào)用返回的錯(cuò)誤。string 表示 error 的描述,它由 C 函數(shù) gai_strerror() 返回。數(shù)字值 error 與本模塊中定義的 EAI_* 常量之一匹配。

在 3.3 版更改: 此類是 OSError 的子類。

exception socket.timeout?

OSError 的子類,當(dāng)套接字發(fā)生超時(shí),且事先已調(diào)用過 settimeout() (或隱式地通過 setdefaulttimeout() )啟用了超時(shí),則會(huì)拋出此異常。附帶的值是一個(gè)字符串,其值總是 "timed out"。

在 3.3 版更改: 此類是 OSError 的子類。

常量?

AF_* 和 SOCK_* 常量現(xiàn)在都在 AddressFamilySocketKind 這兩個(gè) IntEnum 集合內(nèi)。

3.4 新版功能.

socket.AF_UNIX?
socket.AF_INET?
socket.AF_INET6?

這些常量表示地址(和協(xié)議)簇,用于 socket() 的第一個(gè)參數(shù)。如果 AF_UNIX 常量未定義,即表示不支持該協(xié)議。不同系統(tǒng)可能會(huì)有更多其他常量可用。

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

這些常量表示套接字類型,用于 socket() 的第二個(gè)參數(shù)。不同系統(tǒng)可能會(huì)有更多其他常量可用。(一般只有 SOCK_STREAMSOCK_DGRAM 可用)

socket.SOCK_CLOEXEC?
socket.SOCK_NONBLOCK?

這兩個(gè)常量(如果已定義)可以與上述套接字類型結(jié)合使用,并允許你設(shè)置一些原子性的 flags (從而避免可能的競(jìng)爭(zhēng)條件和單獨(dú)調(diào)用的需要)。

可用性: Linux >= 2.6.27。

3.2 新版功能.

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

此列表內(nèi)的許多常量,記載在 Unix 文檔中的套接字和/或 IP 協(xié)議部分,同時(shí)也定義在本 socket 模塊中。它們通常用于套接字對(duì)象的 setsockopt()getsockopt() 方法的參數(shù)中。在大多數(shù)情況下,僅那些在 Unix 頭文件中有定義的符號(hào)會(huì)在本模塊中定義,部分符號(hào)提供了默認(rèn)值。

在 3.6 版更改: 添加了 SO_DOMAINSO_PROTOCOLSO_PEERSECSO_PASSSECTCP_USER_TIMEOUTTCP_CONGESTION

在 3.6.5 版更改: 在 Windows 上,如果 Windows 運(yùn)行時(shí)支持,則 TCP_FASTOPENTCP_KEEPCNT 可用。

在 3.7 版更改: 添加了 TCP_NOTSENT_LOWAT

在 Windows 上,如果 Windows 運(yùn)行時(shí)支持,則 TCP_KEEPIDLETCP_KEEPINTVL 可用。

socket.AF_CAN?
socket.PF_CAN?
SOL_CAN_*
CAN_*

此列表內(nèi)的許多常量,記載在 Linux 文檔中,同時(shí)也定義在本 socket 模塊中。

可用性: Linux >= 2.6.25。

3.3 新版功能.

socket.CAN_BCM?
CAN_BCM_*

CAN 協(xié)議簇內(nèi)的 CAN_BCM 是廣播管理器(Bbroadcast Manager -- BCM)協(xié)議,廣播管理器常量在 Linux 文檔中有所記載,在本 socket 模塊中也有定義。

可用性: Linux >= 2.6.25。

3.4 新版功能.

socket.CAN_RAW_FD_FRAMES?

在 CAN_RAW 套接字中啟用 CAN FD 支持,默認(rèn)是禁用的。它使應(yīng)用程序可以發(fā)送 CAN 和 CAN FD 幀。但是,從套接字讀取時(shí),也必須同時(shí)接受 CAN 和 CAN FD 幀。

此常量在 Linux 文檔中有所記載。

可用性: Linux >= 3.6。

3.5 新版功能.

socket.CAN_ISOTP?

CAN 協(xié)議簇中的 CAN_ISOTP 就是 ISO-TP (ISO 15765-2) 協(xié)議。ISO-TP 常量在 Linux 文檔中有所記載。

可用性: Linux >= 2.6.25。

3.7 新版功能.

socket.AF_PACKET?
socket.PF_PACKET?
PACKET_*

此列表內(nèi)的許多常量,記載在 Linux 文檔中,同時(shí)也定義在本 socket 模塊中。

可用性: Linux >= 2.2。

socket.AF_RDS?
socket.PF_RDS?
socket.SOL_RDS?
RDS_*

此列表內(nèi)的許多常量,記載在 Linux 文檔中,同時(shí)也定義在本 socket 模塊中。

可用性: Linux >= 2.6.30。

3.3 新版功能.

socket.SIO_RCVALL?
socket.SIO_KEEPALIVE_VALS?
socket.SIO_LOOPBACK_FAST_PATH?
RCVALL_*

Windows 的 WSAIoctl() 的常量。這些常量用于套接字對(duì)象的 ioctl() 方法的參數(shù)。

在 3.6 版更改: 添加了 SIO_LOOPBACK_FAST_PATH

TIPC_*

TIPC 相關(guān)常量,與 C socket API 導(dǎo)出的常量一致。更多信息請(qǐng)參閱 TIPC 文檔。

socket.AF_ALG?
socket.SOL_ALG?
ALG_*

用于 Linux 內(nèi)核加密算法的常量。

可用性: Linux >= 2.6.38。

3.6 新版功能.

socket.AF_VSOCK?
socket.IOCTL_VM_SOCKETS_GET_LOCAL_CID?
VMADDR*
SO_VM*

用于 Linux 宿主機(jī)/虛擬機(jī)通訊的常量。

可用性: Linux >= 4.8。

3.7 新版功能.

可用性: BSD、OSX。

3.4 新版功能.

socket.has_ipv6?

本常量為一個(gè)布爾值,該值指示當(dāng)前平臺(tái)是否支持 IPv6。

socket.BDADDR_ANY?
socket.BDADDR_LOCAL?

這些是字符串常量,包含藍(lán)牙地址,這些地址具有特殊含義。例如,當(dāng)用 BTPROTO_RFCOMM 指定綁定套接字時(shí), BDADDR_ANY 表示“任何地址”。

socket.HCI_FILTER?
socket.HCI_TIME_STAMP?
socket.HCI_DATA_DIR?

BTPROTO_HCI 一起使用。 HCI_FILTER 在 NetBSD 或 DragonFlyBSD 上不可用。 HCI_TIME_STAMPHCI_DATA_DIR 在 FreeBSD、NetBSD 或 DragonFlyBSD 上不可用。

函數(shù)?

創(chuàng)建套接字?

下列函數(shù)都能創(chuàng)建 套接字對(duì)象.

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

使用給定的地址簇、套接字類型和協(xié)議號(hào)創(chuàng)建一個(gè)新的套接字。地址簇應(yīng)為 AF_INET (默認(rèn))、AF_INET6AF_UNIXAF_CANAF_PACKETAF_RDS 其中之一。套接字類型應(yīng)為 SOCK_STREAM (默認(rèn))、SOCK_DGRAMSOCK_RAW 或其他 SOCK_ 常量之一。協(xié)議號(hào)通常為零,可以省略,或者在地址簇為 AF_CAN 的情況下,協(xié)議號(hào)應(yīng)為 CAN_RAWCAN_BCMCAN_ISOTP 之一。

如果指定了 fileno,那么將從這一指定的文件描述符中自動(dòng)檢測(cè) familytypeproto 的值。如果調(diào)用本函數(shù)時(shí)顯式指定了 familytypeproto 參數(shù),可以覆蓋自動(dòng)檢測(cè)的值。這只會(huì)影響 Python 表示諸如 socket.getpeername() 一類函數(shù)的返回值的方式,而不影響實(shí)際的操作系統(tǒng)資源。與 socket.fromfd() 不同,fileno 將返回原先的套接字,而不是復(fù)制出新的套接字。這有助于在分離的套接字上調(diào)用 socket.close() 來關(guān)閉它。

新創(chuàng)建的套接字是 不可繼承的

在 3.3 版更改: 添加了 AF_CAN 簇。添加了 AF_RDS 簇。

在 3.4 版更改: 添加了 CAN_BCM 協(xié)議。

在 3.4 版更改: 返回的套接字現(xiàn)在是不可繼承的。

在 3.7 版更改: 添加了 CAN_ISOTP 協(xié)議。

在 3.7 版更改: 當(dāng)將 SOCK_NONBLOCKSOCK_CLOEXEC 標(biāo)志位應(yīng)用于 type 上時(shí),它們會(huì)被清除,且 socket.type 反映不出它們。但它們?nèi)詫鬟f給底層系統(tǒng)的 socket() 調(diào)用。因此,

sock = socket.socket(
    socket.AF_INET,
    socket.SOCK_STREAM | socket.SOCK_NONBLOCK)

仍將在支持 SOCK_NONBLOCK 的系統(tǒng)上創(chuàng)建一個(gè)非阻塞的套接字,但是 sock.type 會(huì)被置為 socket.SOCK_STREAM

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

構(gòu)建一對(duì)已連接的套接字對(duì)象,使用給定的地址簇、套接字類型和協(xié)議號(hào)。地址簇、套接字類型和協(xié)議號(hào)與上述 socket() 函數(shù)相同。默認(rèn)地址簇為 AF_UNIX (需要當(dāng)前平臺(tái)支持,不支持則默認(rèn)為 AF_INET )。

新創(chuàng)建的套接字都是 不可繼承的

在 3.2 版更改: 現(xiàn)在,返回的套接字對(duì)象支持全部套接字 API,而不是全部 API 的一個(gè)子集。

在 3.4 版更改: 返回的套接字現(xiàn)在都是不可繼承的。

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

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

連接到一個(gè) TCP 服務(wù),該服務(wù)正在偵聽 Internet address (用二元組 (host, port) 表示)。連接后返回套接字對(duì)象。這是比 socket.connect() 更高級(jí)的函數(shù):如果 host 是非數(shù)字主機(jī)名,它將嘗試從 AF_INETAF_INET6 解析它,然后依次嘗試連接到所有可能的地址,直到連接成功。這使得編寫兼容 IPv4 和 IPv6 的客戶端變得容易。

傳入可選參數(shù) timeout 可以在套接字實(shí)例上設(shè)置超時(shí)(在嘗試連接前)。如果未提供 timeout,則使用由 getdefaulttimeout() 返回的全局默認(rèn)超時(shí)設(shè)置。

如果提供了 source_address,它必須為二元組 (host, port),以便套接字在連接之前綁定為其源地址。如果 host 或 port 分別為 '' 或 0,則使用操作系統(tǒng)默認(rèn)行為。

在 3.2 版更改: 添加了*source_address* 參數(shù)

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

復(fù)制文件描述符 fd (一個(gè)由文件對(duì)象的 fileno() 方法返回的整數(shù)),然后從結(jié)果中構(gòu)建一個(gè)套接字對(duì)象。地址簇、套接字類型和協(xié)議號(hào)與上述 socket() 函數(shù)相同。文件描述符應(yīng)指向一個(gè)套接字,但不會(huì)專門去檢查——如果文件描述符是無效的,則對(duì)該對(duì)象的后續(xù)操作可能會(huì)失敗。本函數(shù)很少用到,但是在將套接字作為標(biāo)準(zhǔn)輸入或輸出傳遞給程序(如 Unix inet 守護(hù)程序啟動(dòng)的服務(wù)器)時(shí),可以使用本函數(shù)獲取或設(shè)置套接字選項(xiàng)。套接字須處于阻塞模式。

新創(chuàng)建的套接字是 不可繼承的

在 3.4 版更改: 返回的套接字現(xiàn)在是不可繼承的。

socket.fromshare(data)?

根據(jù) socket.share() 方法獲得的數(shù)據(jù)實(shí)例化套接字。套接字須處于阻塞模式。

可用性: Windows。

3.3 新版功能.

socket.SocketType?

這是一個(gè) Python 類型對(duì)象,表示套接字對(duì)象的類型。它等同于 type(socket(...))

其他功能?

socket 模塊還提供各種與網(wǎng)絡(luò)相關(guān)的服務(wù):

socket.close(fd)?

關(guān)閉一個(gè)套接字文件描述符。它類似于 os.close(),但專用于套接字。在某些平臺(tái)上(特別是在 Windows 上),os.close() 對(duì)套接字文件描述符無效。

3.7 新版功能.

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

host/port 參數(shù)轉(zhuǎn)換為 5 元組的序列,其中包含創(chuàng)建(連接到某服務(wù)的)套接字所需的所有參數(shù)。host 是域名,是字符串格式的 IPv4/v6 地址或 Noneport 是字符串格式的服務(wù)名稱,如 'http' 、端口號(hào)(數(shù)字)或 None。傳入 None 作為 hostport 的值,相當(dāng)于將 NULL 傳遞給底層 C API。

可以指定 familytypeproto 參數(shù),以縮小返回的地址列表。向這些參數(shù)分別傳入 0 表示保留全部結(jié)果范圍。flags 參數(shù)可以是 AI_* 常量中的一個(gè)或多個(gè),它會(huì)影響結(jié)果的計(jì)算和返回。例如,AI_NUMERICHOST 會(huì)禁用域名解析,此時(shí)如果 host 是域名,則會(huì)拋出錯(cuò)誤。

本函數(shù)返回的 5 元組列表具有以下結(jié)構(gòu):

(family, type, proto, canonname, sockaddr)

在這些元組中,familytypeproto 都是整數(shù),可以用于傳遞給 socket() 函數(shù)。如果 flags 參數(shù)有一部分是 AI_CANONNAME,那么 canonname 將是表示 host 的規(guī)范名稱的字符串。否則 canonname 將為空。sockaddr 是一個(gè)表示套接字地址的元組,具體格式取決于返回的 family (對(duì)于 AF_INET,是一個(gè) (address, port) 二元組,對(duì)于 AF_INET6,是一個(gè) (address, port, flow info, scope id) 四元組),可以用于傳遞給 socket.connect() 方法。

下面的示例獲取了 TCP 連接地址信息,假設(shè)該連接通過 80 端口連接至 example.org?(如果系統(tǒng)未啟用 IPv6,則結(jié)果可能會(huì)不同):

>>> 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 版更改: 現(xiàn)在可以使用關(guān)鍵字參數(shù)的形式來傳遞參數(shù)。

在 3.7 版更改: 對(duì)于 IPv6 多播地址,表示地址的字符串將不包含 %scope 部分。

socket.getfqdn([name])?

返回 name 的全限定域名 (Fully Qualified Domain Name -- FQDN)。如果 name 省略或?yàn)榭眨瑒t將其解釋為本地主機(jī)。為了查找全限定名稱,首先將檢查由 gethostbyaddr() 返回的主機(jī)名,然后是主機(jī)的別名(如果存在)。選中第一個(gè)包含句點(diǎn)的名字。如果無法獲取全限定域名,則返回由 gethostname() 返回的主機(jī)名。

socket.gethostbyname(hostname)?

將主機(jī)名轉(zhuǎn)換為 IPv4 地址格式。IPv4 地址以字符串格式返回,如 '100.50.200.5'。如果主機(jī)名本身是 IPv4 地址,則原樣返回。更完整的接口請(qǐng)參考 gethostbyname_ex()gethostbyname() 不支持 IPv6 域名解析,應(yīng)使用 getaddrinfo() 來支持 IPv4/v6 雙協(xié)議棧。

socket.gethostbyname_ex(hostname)?

將主機(jī)名轉(zhuǎn)換為 IPv4 地址格式的擴(kuò)展接口。返回三元組 (hostname, aliaslist, ipaddrlist),其中 hostname 是響應(yīng)給定 ip_address 的主要主機(jī)名,aliaslist 是相同地址的其他可用主機(jī)名的列表(可能為空),而 ipaddrlist 是 IPv4 地址列表,包含相同主機(jī)名、相同接口的不同地址(通常是一個(gè)地址,但不總是如此)。gethostbyname_ex() 不支持 IPv6 名稱解析,應(yīng)使用 getaddrinfo() 來支持 IPv4/v6 雙協(xié)議棧。

socket.gethostname()?

返回一個(gè)字符串,包含當(dāng)前正在運(yùn)行 Python 解釋器的機(jī)器的主機(jī)名。

注意: gethostname() 并不總是返回全限定域名,必要的話請(qǐng)使用 getfqdn()

socket.gethostbyaddr(ip_address)?

返回三元組 (hostname, aliaslist, ipaddrlist),其中 hostname 是響應(yīng)給定 ip_address 的主要主機(jī)名,aliaslist 是相同地址的其他可用主機(jī)名的列表(可能為空),而 ipaddrlist 是 IPv4/v6 地址列表,包含相同主機(jī)名、相同接口的不同地址(很可能僅包含一個(gè)地址)。要查詢?nèi)薅ㄓ蛎?qǐng)使用函數(shù) getfqdn()gethostbyaddr() 支持 IPv4 和 IPv6。

socket.getnameinfo(sockaddr, flags)?

將套接字地址 sockaddr 轉(zhuǎn)換為二元組 (host, port)host 的形式可能是全限定域名,或是由數(shù)字表示的地址,具體取決于 flags 的設(shè)置。同樣,port 可以包含字符串格式的端口名稱或數(shù)字格式的端口號(hào)。

對(duì)于 IPv6 地址,如果 sockaddr 包含有意義的 scopeid,則將 %scope 附加到 host 部分。這種情況通常發(fā)生在多播地址上。

socket.getprotobyname(protocolname)?

將 Internet 協(xié)議名稱(如 'icmp' )轉(zhuǎn)換為常量,該常量適用于 socket() 函數(shù)的第三個(gè)(可選)參數(shù)。通常只有在 "raw" 模式 (SOCK_RAW) 中打開的套接字才需要使用該常量。對(duì)于正常的套接字模式,協(xié)議省略或?yàn)榱銜r(shí),會(huì)自動(dòng)選擇正確的協(xié)議。

socket.getservbyname(servicename[, protocolname])?

將 Internet 服務(wù)名稱和協(xié)議名稱轉(zhuǎn)換為該服務(wù)的端口號(hào)。協(xié)議名稱是可選的,如果提供的話應(yīng)為 'tcp''udp',否則將匹配出所有協(xié)議。

socket.getservbyport(port[, protocolname])?

將 Internet 端口號(hào)和協(xié)議名稱轉(zhuǎn)換為該服務(wù)的服務(wù)名稱。協(xié)議名稱是可選的,如果提供的話應(yīng)為 'tcp''udp',否則將匹配出所有協(xié)議。

socket.ntohl(x)?

將 32 位正整數(shù)從網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序。在主機(jī)字節(jié)序與網(wǎng)絡(luò)字節(jié)序相同的計(jì)算機(jī)上,這是一個(gè)空操作。字節(jié)序不同將執(zhí)行 4 字節(jié)交換操作。

socket.ntohs(x)?

將 16 位正整數(shù)從網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序。在主機(jī)字節(jié)序與網(wǎng)絡(luò)字節(jié)序相同的計(jì)算機(jī)上,這是一個(gè)空操作。字節(jié)序不同將執(zhí)行 2 字節(jié)交換操作。

3.7 版后已移除: 如果 x 不符合 16 位無符號(hào)整數(shù),但符合 C 語言的正整數(shù),則它會(huì)被靜默截?cái)酁?16 位無符號(hào)整數(shù)。此靜默截?cái)喙δ芤褩売茫磥戆姹镜?Python 將對(duì)此拋出異常。

socket.htonl(x)?

將 32 位正整數(shù)從主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序。在主機(jī)字節(jié)序與網(wǎng)絡(luò)字節(jié)序相同的計(jì)算機(jī)上,這是一個(gè)空操作。字節(jié)序不同將執(zhí)行 4 字節(jié)交換操作。

socket.htons(x)?

將 16 位正整數(shù)從主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序。在主機(jī)字節(jié)序與網(wǎng)絡(luò)字節(jié)序相同的計(jì)算機(jī)上,這是一個(gè)空操作。字節(jié)序不同將執(zhí)行 2 字節(jié)交換操作。

3.7 版后已移除: 如果 x 不符合 16 位無符號(hào)整數(shù),但符合 C 語言的正整數(shù),則它會(huì)被靜默截?cái)酁?16 位無符號(hào)整數(shù)。此靜默截?cái)喙δ芤褩売茫磥戆姹镜?Python 將對(duì)此拋出異常。

socket.inet_aton(ip_string)?

將 IPv4 地址從點(diǎn)分十進(jìn)制字符串格式(如 '123.45.67.89' )轉(zhuǎn)換為 32 位壓縮二進(jìn)制格式,轉(zhuǎn)換后為字節(jié)對(duì)象,長(zhǎng)度為四個(gè)字符。與那些使用標(biāo)準(zhǔn) C 庫,且需要 struct in_addr 類型的對(duì)象的程序交換信息時(shí),此功能很有用。 該類型即此函數(shù)返回的 32 位壓縮二進(jìn)制的 C 類型。

inet_aton() 也接受句點(diǎn)數(shù)少于三的字符串,詳情請(qǐng)參閱 Unix 手冊(cè) inet(3)

如果傳入本函數(shù)的 IPv4 地址字符串無效,則拋出 OSError。注意,具體什么樣的地址有效取決于 inet_aton() 的底層 C 實(shí)現(xiàn)。

inet_aton() 不支持 IPv6,在 IPv4/v6 雙協(xié)議棧下應(yīng)使用 inet_pton() 來代替。

socket.inet_ntoa(packed_ip)?

將 32 位壓縮 IPv4 地址(一個(gè) 類字節(jié)對(duì)象,長(zhǎng) 4 個(gè)字節(jié))轉(zhuǎn)換為標(biāo)準(zhǔn)的點(diǎn)分十進(jìn)制字符串形式(如 '123.45.67.89' )。與那些使用標(biāo)準(zhǔn) C 庫,且需要 struct in_addr 類型的對(duì)象的程序交換信息時(shí),本函數(shù)很有用。 該類型即本函數(shù)參數(shù)中的 32 位壓縮二進(jìn)制數(shù)據(jù)的 C 類型。

如果傳入本函數(shù)的字節(jié)序列長(zhǎng)度不是 4 個(gè)字節(jié),則拋出 OSErrorinet_ntoa() 不支持 IPv6,在 IPv4/v6 雙協(xié)議棧下應(yīng)使用 inet_ntop() 來代替。

在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對(duì)象

socket.inet_pton(address_family, ip_string)?

將特定地址簇的 IP 地址(字符串)轉(zhuǎn)換為壓縮二進(jìn)制格式。當(dāng)庫或網(wǎng)絡(luò)協(xié)議需要接受 struct in_addr 類型的對(duì)象(類似 inet_aton() )或 struct in6_addr 類型的對(duì)象時(shí),inet_pton() 很有用。

目前 address_family 支持 AF_INETAF_INET6。如果 IP 地址字符串 ip_string 無效,則拋出 OSError。注意,具體什么地址有效取決于 address_family 的值和 inet_pton() 的底層實(shí)現(xiàn)。

可用性: Unix(可能非所有平臺(tái)都可用)、Windows。

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

socket.inet_ntop(address_family, packed_ip)?

將壓縮 IP 地址(一個(gè) 類字節(jié)對(duì)象,數(shù)個(gè)字節(jié)長(zhǎng))轉(zhuǎn)換為標(biāo)準(zhǔn)的、特定地址簇的字符串形式(如 '7.10.0.5''5aef:2b::8' )。當(dāng)庫或網(wǎng)絡(luò)協(xié)議返回 struct in_addr 類型的對(duì)象(類似 inet_ntoa() )或 struct in6_addr 類型的對(duì)象時(shí),inet_ntop() 很有用。

目前 address_family 支持 AF_INETAF_INET6。如果字節(jié)對(duì)象 packed_ip 與指定的地址簇長(zhǎng)度不符,則拋出 ValueError。針對(duì) inet_ntop() 調(diào)用的錯(cuò)誤則拋出 OSError

可用性: Unix(可能非所有平臺(tái)都可用)、Windows。

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

在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對(duì)象

socket.CMSG_LEN(length)?

返回給定 length 所關(guān)聯(lián)數(shù)據(jù)的輔助數(shù)據(jù)項(xiàng)的總長(zhǎng)度(不帶尾部填充)。此值通常用作 recvmsg() 接收一個(gè)輔助數(shù)據(jù)項(xiàng)的緩沖區(qū)大小,但是 RFC 3542 要求可移植應(yīng)用程序使用 CMSG_SPACE(),以此將尾部填充的空間計(jì)入,即使該項(xiàng)在緩沖區(qū)的最后。如果 length 超出允許范圍,則拋出 OverflowError

可用性: 大多數(shù) Unix 平臺(tái),其他平臺(tái)也可能可用。

3.3 新版功能.

socket.CMSG_SPACE(length)?

返回 recvmsg() 所需的緩沖區(qū)大小,以接收給定 length 所關(guān)聯(lián)數(shù)據(jù)的輔助數(shù)據(jù)項(xiàng),帶有尾部填充。接收多個(gè)項(xiàng)目所需的緩沖區(qū)空間是關(guān)聯(lián)數(shù)據(jù)長(zhǎng)度的 CMSG_SPACE() 值的總和。如果 length 超出允許范圍,則拋出 OverflowError

請(qǐng)注意,某些系統(tǒng)可能支持輔助數(shù)據(jù),但不提供本函數(shù)。還需注意,如果使用本函數(shù)的結(jié)果來設(shè)置緩沖區(qū)大小,可能無法精確限制可接收的輔助數(shù)據(jù)量,因?yàn)榭赡軙?huì)有其他數(shù)據(jù)寫入尾部填充區(qū)域。

可用性: 大多數(shù) Unix 平臺(tái),其他平臺(tái)也可能可用。

3.3 新版功能.

socket.getdefaulttimeout()?

返回用于新套接字對(duì)象的默認(rèn)超時(shí)(以秒為單位的浮點(diǎn)數(shù))。值 None 表示新套接字對(duì)象沒有超時(shí)。首次導(dǎo)入 socket 模塊時(shí),默認(rèn)值為 None

socket.setdefaulttimeout(timeout)?

設(shè)置用于新套接字對(duì)象的默認(rèn)超時(shí)(以秒為單位的浮點(diǎn)數(shù))。首次導(dǎo)入 socket 模塊時(shí),默認(rèn)值為 None。可能的取值及其各自的含義請(qǐng)參閱 settimeout()

socket.sethostname(name)?

將計(jì)算機(jī)的主機(jī)名設(shè)置為 name。如果權(quán)限不足將拋出 OSError

可用性: Unix。

3.3 新版功能.

socket.if_nameindex()?

返回一個(gè)列表,包含網(wǎng)絡(luò)接口(網(wǎng)卡)信息二元組(整數(shù)索引,名稱字符串)。系統(tǒng)調(diào)用失敗則拋出 OSError

可用性: Unix。

3.3 新版功能.

socket.if_nametoindex(if_name)?

返回網(wǎng)絡(luò)接口名稱相對(duì)應(yīng)的索引號(hào)。如果沒有所給名稱的接口,則拋出 OSError

可用性: Unix。

3.3 新版功能.

socket.if_indextoname(if_index)?

返回網(wǎng)絡(luò)接口索引號(hào)相對(duì)應(yīng)的接口名稱。如果沒有所給索引號(hào)的接口,則拋出 OSError

可用性: Unix。

3.3 新版功能.

套接字對(duì)象?

套接字對(duì)象具有以下方法。除了 makefile(),其他都與套接字專用的 Unix 系統(tǒng)調(diào)用相對(duì)應(yīng)。

在 3.2 版更改: 添加了對(duì) 上下文管理器 協(xié)議的支持。退出上下文管理器與調(diào)用 close() 等效。

socket.accept()?

接受一個(gè)連接。此 socket 必須綁定到一個(gè)地址上并且監(jiān)聽連接。返回值是一個(gè) (conn, address) 對(duì),其中 conn 是一個(gè) 的套接字對(duì)象,用于在此連接上收發(fā)數(shù)據(jù),address 是連接另一端的套接字所綁定的地址。

新創(chuàng)建的套接字是 不可繼承的

在 3.4 版更改: 該套接字現(xiàn)在是不可繼承的。

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

socket.bind(address)?

將套接字綁定到 address。套接字必須尚未綁定。( address 的格式取決于地址簇 —— 參見上文)

socket.close()?

將套接字標(biāo)記為關(guān)閉。當(dāng) makefile() 創(chuàng)建的所有文件對(duì)象都關(guān)閉時(shí),底層系統(tǒng)資源(如文件描述符)也將關(guān)閉。一旦上述情況發(fā)生,將來對(duì)套接字對(duì)象的所有操作都會(huì)失敗。對(duì)端將接收不到任何數(shù)據(jù)(清空隊(duì)列數(shù)據(jù)后)。

垃圾回收時(shí),套接字會(huì)自動(dòng)關(guān)閉,但建議顯式 close() 它們,或在它們周圍使用 with 語句。

在 3.6 版更改: 現(xiàn)在,如果底層的 close() 調(diào)用出錯(cuò),會(huì)拋出 OSError

注解

close() 釋放與連接相關(guān)聯(lián)的資源,但不一定立即關(guān)閉連接。如果需要及時(shí)關(guān)閉連接,請(qǐng)?jiān)谡{(diào)用 close() 之前調(diào)用 shutdown()

socket.connect(address)?

連接到 address 處的遠(yuǎn)程套接字。( address 的格式取決于地址簇 —— 參見上文)

如果連接被信號(hào)中斷,則本方法將等待,直到連接完成。如果信號(hào)處理程序未拋出異常,且套接字阻塞中或已超時(shí),則在超時(shí)后拋出 socket.timeout。對(duì)于非阻塞套接字,如果連接被信號(hào)中斷,則本方法將拋出 InterruptedError 異常(或信號(hào)處理程序拋出的異常)。

在 3.5 版更改: 本方法現(xiàn)在將等待,直到連接完成,而不是在以下情況拋出 InterruptedError 異常。該情況為,連接被信號(hào)中斷,信號(hào)處理程序未拋出異常,且套接字阻塞中或已超時(shí)(具體解釋請(qǐng)參閱 PEP 475 )。

socket.connect_ex(address)?

類似于 connect(address),但是對(duì)于 C 級(jí)別的 connect() 調(diào)用返回的錯(cuò)誤,本函數(shù)將返回錯(cuò)誤指示器,而不是拋出異常(對(duì)于其他問題,如“找不到主機(jī)”,仍然可以拋出異常)。如果操作成功,則錯(cuò)誤指示器為 0,否則為 errno 變量的值。這對(duì)支持如異步連接很有用。

socket.detach()?

將套接字對(duì)象置于關(guān)閉狀態(tài),而底層的文件描述符實(shí)際并不關(guān)閉。返回該文件描述符,使其可以重新用于其他目的。

3.2 新版功能.

socket.dup()?

創(chuàng)建套接字的副本。

新創(chuàng)建的套接字是 不可繼承的

在 3.4 版更改: 該套接字現(xiàn)在是不可繼承的。

socket.fileno()?

返回套接字的文件描述符(一個(gè)小整數(shù)),失敗返回 -1。配合 select.select() 使用很有用。

在 Windows 下,此方法返回的小整數(shù)在允許使用文件描述符的地方無法使用(如 os.fdopen() )。Unix 無此限制。

socket.get_inheritable()?

獲取套接字文件描述符或套接字句柄的 可繼承標(biāo)志 :如果子進(jìn)程可以繼承套接字則為 True,否則為 False

3.4 新版功能.

socket.getpeername()?

返回套接字連接到的遠(yuǎn)程地址。舉例而言,這可以用于查找遠(yuǎn)程 IPv4/v6 套接字的端口號(hào)。(返回的地址格式取決于地址簇 —— 參見上文。)部分系統(tǒng)不支持此函數(shù)。

socket.getsockname()?

返回套接字本身的地址。舉例而言,這可以用于查找 IPv4/v6 套接字的端口號(hào)。(返回的地址格式取決于地址簇 —— 參見上文。)

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

返回指定套接字選項(xiàng)的值(參閱 Unix 手冊(cè)頁 getsockopt(2) )。所需的符號(hào)常量( SO_* 等)已定義在本模塊中。如果未指定 buflen,則認(rèn)為該選項(xiàng)值為整數(shù),由本函數(shù)返回該整數(shù)值。如果指定 buflen,則它定義了用于存放選項(xiàng)值的緩沖區(qū)的最大長(zhǎng)度,且該緩沖區(qū)將作為字節(jié)對(duì)象返回。對(duì)緩沖區(qū)的解碼工作由調(diào)用者自行完成(針對(duì)編碼為字節(jié)串的 C 結(jié)構(gòu),其解碼方法請(qǐng)參閱可選的內(nèi)置模塊 struct )。

socket.getblocking()?

如果套接字處于阻塞模式,返回 True,非阻塞模式返回 False

這相當(dāng)于檢測(cè) socket.gettimeout() == 0

3.7 新版功能.

socket.gettimeout()?

返回套接字操作相關(guān)的超時(shí)秒數(shù)(浮點(diǎn)數(shù)),未設(shè)置超時(shí)則返回 None。它反映最后一次調(diào)用 setblocking()settimeout() 后的設(shè)置。

socket.ioctl(control, option)?
平臺(tái)

Windows

ioctl() 方法是 WSAIoctl 系統(tǒng)接口的有限接口。請(qǐng)參考 Win32 文檔 以獲取更多信息。

在其他平臺(tái)上,可以使用通用的 fcntl.fcntl()fcntl.ioctl() 函數(shù),它們接受套接字對(duì)象作為第一個(gè)參數(shù)。

當(dāng)前僅支持以下控制碼: SIO_RCVALLSIO_KEEPALIVE_VALSSIO_LOOPBACK_FAST_PATH

在 3.6 版更改: 添加了 SIO_LOOPBACK_FAST_PATH

socket.listen([backlog])?

啟動(dòng)一個(gè)服務(wù)器用于接受連接。如果指定 backlog,則它最低為 0(小于 0 會(huì)被置為 0),它指定系統(tǒng)允許暫未 accept 的連接數(shù),超過后將拒絕新連接。未指定則自動(dòng)設(shè)為合理的默認(rèn)值。

在 3.5 版更改: backlog 參數(shù)現(xiàn)在是可選的。

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

返回與套接字關(guān)聯(lián)的 文件對(duì)象。返回的對(duì)象的具體類型取決于 makefile() 的參數(shù)。這些參數(shù)的解釋方式與內(nèi)置的 open() 函數(shù)相同,其中 mode 的值僅支持 'r' (默認(rèn)),'w''b'

套接字必須處于阻塞模式,它可以有超時(shí),但是如果發(fā)生超時(shí),文件對(duì)象的內(nèi)部緩沖區(qū)可能會(huì)以不一致的狀態(tài)結(jié)尾。

關(guān)閉 makefile() 返回的文件對(duì)象不會(huì)關(guān)閉原始套接字,除非所有其他文件對(duì)象都已關(guān)閉且在套接字對(duì)象上調(diào)用了 socket.close()

注解

在 Windows 上,由 makefile() 創(chuàng)建的文件類對(duì)象無法作為帶文件描述符的文件對(duì)象使用,如無法作為 subprocess.Popen() 的流參數(shù)。

socket.recv(bufsize[, flags])?

從套接字接收數(shù)據(jù)。返回值是一個(gè)字節(jié)對(duì)象,表示接收到的數(shù)據(jù)。bufsize 指定一次接收的最大數(shù)據(jù)量。可選參數(shù) flags 的含義請(qǐng)參閱 Unix 手冊(cè)頁 recv(2),它默認(rèn)為零。

注解

為了最佳匹配硬件和網(wǎng)絡(luò)的實(shí)際情況,bufsize 的值應(yīng)為 2 的相對(duì)較小的冪,如 4096。

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

socket.recvfrom(bufsize[, flags])?

從套接字接收數(shù)據(jù)。返回值是一對(duì) (bytes, address),其中 bytes 是字節(jié)對(duì)象,表示接收到的數(shù)據(jù),address 是發(fā)送端套接字的地址。可選參數(shù) flags 的含義請(qǐng)參閱 Unix 手冊(cè)頁 recv(2),它默認(rèn)為零。( address 的格式取決于地址簇 —— 參見上文)

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

在 3.7 版更改: 對(duì)于多播 IPv6 地址,address 的第一項(xiàng)不再包含 %scope 部分。要獲得完整的 IPv6 地址,請(qǐng)使用 getnameinfo()

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

從套接字接收普通數(shù)據(jù)(至多 bufsize 字節(jié))和輔助數(shù)據(jù)。ancbufsize 參數(shù)設(shè)置用于接收輔助數(shù)據(jù)的內(nèi)部緩沖區(qū)的大小(以字節(jié)為單位),默認(rèn)為 0,表示不接收輔助數(shù)據(jù)。可以使用 CMSG_SPACE()CMSG_LEN() 計(jì)算輔助數(shù)據(jù)緩沖區(qū)的合適大小,無法放入緩沖區(qū)的項(xiàng)目可能會(huì)被截?cái)嗷騺G棄。flags 參數(shù)默認(rèn)為 0,其含義與 recv() 中的相同。

返回值是一個(gè)四元組: (data, ancdata, msg_flags, address)data 項(xiàng)是一個(gè) bytes 對(duì)象,用于保存接收到的非輔助數(shù)據(jù)。ancdata 項(xiàng)是零個(gè)或多個(gè)元組 (cmsg_level, cmsg_type, cmsg_data) 組成的列表,表示接收到的輔助數(shù)據(jù)(控制消息):cmsg_levelcmsg_type 是分別表示協(xié)議級(jí)別和協(xié)議類型的整數(shù),而 cmsg_data 是保存相關(guān)數(shù)據(jù)的 bytes 對(duì)象。msg_flags 項(xiàng)由各種標(biāo)志按位或組成,表示接收消息的情況,詳細(xì)信息請(qǐng)參閱系統(tǒng)文檔。如果接收端套接字?jǐn)嚅_連接,則 address 是發(fā)送端套接字的地址(如果有),否則該值無指定。

某些系統(tǒng)上可以利用 AF_UNIX 套接字通過 sendmsg()recvmsg() 在進(jìn)程之間傳遞文件描述符。使用此功能時(shí)(通常僅限于 SOCK_STREAM 套接字),recvmsg() 將在其輔助數(shù)據(jù)中返回以下格式的項(xiàng) (socket.SOL_SOCKET, socket.SCM_RIGHTS, fds),其中 fds 是一個(gè) bytes 對(duì)象,是新文件描述符表示為原生 C int 類型的二進(jìn)制數(shù)組。如果 recvmsg() 在系統(tǒng)調(diào)用返回后拋出異常,它將首先關(guān)閉此機(jī)制接收到的所有文件描述符。

對(duì)于僅接收到一部分的輔助數(shù)據(jù)項(xiàng),一些系統(tǒng)沒有指示其截?cái)嚅L(zhǎng)度。如果某個(gè)項(xiàng)目可能超出了緩沖區(qū)的末尾,recvmsg() 將發(fā)出 RuntimeWarning,并返回其在緩沖區(qū)內(nèi)的部分,前提是該對(duì)象被截?cái)嘤陉P(guān)聯(lián)數(shù)據(jù)開始后。

在支持 SCM_RIGHTS 機(jī)制的系統(tǒng)上,下方的函數(shù)將最多接收 maxfds 個(gè)文件描述符,返回消息數(shù)據(jù)和包含描述符的列表(同時(shí)忽略意外情況,如接收到無關(guān)的控制消息)。另請(qǐng)參閱 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.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])
    return msg, list(fds)

可用性: 大多數(shù) Unix 平臺(tái),其他平臺(tái)也可能可用。

3.3 新版功能.

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

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

從套接字接收普通數(shù)據(jù)和輔助數(shù)據(jù),其行為與 recvmsg() 相同,但將非輔助數(shù)據(jù)分散到一系列緩沖區(qū)中,而不是返回新的字節(jié)對(duì)象。buffers 參數(shù)必須是可迭代對(duì)象,它迭代出可供寫入的緩沖區(qū)(如 bytearray 對(duì)象),這些緩沖區(qū)將被連續(xù)的非輔助數(shù)據(jù)塊填充,直到數(shù)據(jù)全部寫完或緩沖區(qū)用完為止。在允許使用的緩沖區(qū)數(shù)量上,操作系統(tǒng)可能會(huì)有限制( sysconf()SC_IOV_MAX 值)。ancbufsizeflags 參數(shù)的含義與 recvmsg() 中的相同。

返回值為四元組: (nbytes, ancdata, msg_flags, address),其中 nbytes 是寫入緩沖區(qū)的非輔助數(shù)據(jù)的字節(jié)總數(shù),而 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---')]

可用性: 大多數(shù) Unix 平臺(tái),其他平臺(tái)也可能可用。

3.3 新版功能.

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

從套接字接收數(shù)據(jù),將其寫入 buffer 而不是創(chuàng)建新的字節(jié)串。返回值是一對(duì) (nbytes, address),其中 nbytes 是收到的字節(jié)數(shù),address 是發(fā)送端套接字的地址。可選參數(shù) flags 的含義請(qǐng)參閱 Unix 手冊(cè)頁 recv(2),它默認(rèn)為零。( address 的格式取決于地址簇 —— 參見上文)

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

從套接字接收至多 nbytes 個(gè)字節(jié),將其寫入緩沖區(qū)而不是創(chuàng)建新的字節(jié)串。如果 nbytes 未指定(或指定為 0),則接收至所給緩沖區(qū)的最大可用大小。返回接收到的字節(jié)數(shù)。可選參數(shù) flags 的含義請(qǐng)參閱 Unix 手冊(cè)頁 recv(2),它默認(rèn)為零。

socket.send(bytes[, flags])?

發(fā)送數(shù)據(jù)給套接字。本套接字必須已連接到遠(yuǎn)程套接字。可選參數(shù) flags?的含義與上述 recv() 中的相同。本方法返回已發(fā)送的字節(jié)數(shù)。應(yīng)用程序要負(fù)責(zé)檢查所有數(shù)據(jù)是否已發(fā)送,如果僅傳輸了部分?jǐn)?shù)據(jù),程序需要自行嘗試傳輸其余數(shù)據(jù)。有關(guān)該主題的更多信息,請(qǐng)參考 套接字編程指南

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

socket.sendall(bytes[, flags])?

發(fā)送數(shù)據(jù)給套接字。本套接字必須已連接到遠(yuǎn)程套接字。可選參數(shù) flags 的含義與上述 recv() 中的相同。與 send() 不同,本方法持續(xù)從 bytes 發(fā)送數(shù)據(jù),直到所有數(shù)據(jù)都已發(fā)送或發(fā)生錯(cuò)誤為止。成功后會(huì)返回 None。出錯(cuò)后會(huì)拋出一個(gè)異常,此時(shí)并沒有辦法確定成功發(fā)送了多少數(shù)據(jù)。

在 3.5 版更改: 每次成功發(fā)送數(shù)據(jù)后,套接字超時(shí)不再重置。現(xiàn)在,套接字超時(shí)是發(fā)送所有數(shù)據(jù)的最大總持續(xù)時(shí)間。

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

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

發(fā)送數(shù)據(jù)給套接字。本套接字不應(yīng)連接到遠(yuǎn)程套接字,而應(yīng)由 address 指定目標(biāo)套接字。可選參數(shù) flags 的含義與上述 recv() 中的相同。本方法返回已發(fā)送的字節(jié)數(shù)。( address 的格式取決于地址簇 —— 參見上文。)

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

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

將普通數(shù)據(jù)和輔助數(shù)據(jù)發(fā)送給套接字,將從一系列緩沖區(qū)中收集非輔助數(shù)據(jù),并將其拼接為一條消息。buffers 參數(shù)指定的非輔助數(shù)據(jù)應(yīng)為可迭代的 字節(jié)類對(duì)象 (如 bytes 對(duì)象),在允許使用的緩沖區(qū)數(shù)量上,操作系統(tǒng)可能會(huì)有限制( sysconf()SC_IOV_MAX 值)。ancdata 參數(shù)指定的輔助數(shù)據(jù)(控制消息)應(yīng)為可迭代對(duì)象,迭代出零個(gè)或多個(gè) (cmsg_level, cmsg_type, cmsg_data) 元組,其中 cmsg_levelcmsg_type 是分別指定協(xié)議級(jí)別和協(xié)議類型的整數(shù),而 cmsg_data 是保存相關(guān)數(shù)據(jù)的字節(jié)類對(duì)象。請(qǐng)注意,某些系統(tǒng)(特別是沒有 CMSG_SPACE() 的系統(tǒng))可能每次調(diào)用僅支持發(fā)送一條控制消息。flags 參數(shù)默認(rèn)為 0,與 send() 中的含義相同。如果 address 指定為除 None 以外的值,它將作為消息的目標(biāo)地址。返回值是已發(fā)送的非輔助數(shù)據(jù)的字節(jié)數(shù)。

在支持 SCM_RIGHTS 機(jī)制的系統(tǒng)上,下方的函數(shù)通過一個(gè) AF_UNIX 套接字來發(fā)送文件描述符列表 fds。另請(qǐng)參閱 recvmsg()

import socket, array

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

可用性: 大多數(shù) Unix 平臺(tái),其他平臺(tái)也可能可用。

3.3 新版功能.

在 3.5 版更改: 如果系統(tǒng)調(diào)用被中斷,但信號(hào)處理程序沒有觸發(fā)異常,此方法現(xiàn)在會(huì)重試系統(tǒng)調(diào)用,而不是觸發(fā) InterruptedError 異常 (原因詳見 PEP 475)。

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

AF_ALG 套接字定制的 sendmsg() 版本。可為 AF_ALG 套接字設(shè)置模式、IV、AEAD 關(guān)聯(lián)數(shù)據(jù)的長(zhǎng)度和標(biāo)志位。

可用性: Linux >= 2.6.38。

3.6 新版功能.

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

使用高性能的 os.sendfile 發(fā)送文件,直到達(dá)到文件的 EOF 為止,返回已發(fā)送的字節(jié)總數(shù)。file 必須是一個(gè)以二進(jìn)制模式打開的常規(guī)文件對(duì)象。如果 os.sendfile 不可用(如 Windows)或 file 不是常規(guī)文件,將使用 send() 代替。offset 指示從哪里開始讀取文件。如果指定了 count,它確定了要發(fā)送的字節(jié)總數(shù),而不會(huì)持續(xù)發(fā)送直到達(dá)到文件的 EOF。返回時(shí)或發(fā)生錯(cuò)誤時(shí),文件位置將更新,在這種情況下,file.tell() 可用于確定已發(fā)送的字節(jié)數(shù)。套接字必須為 SOCK_STREAM 類型。不支持非阻塞的套接字。

3.5 新版功能.

socket.set_inheritable(inheritable)?

設(shè)置套接字文件描述符或套接字句柄的 可繼承標(biāo)志

3.4 新版功能.

socket.setblocking(flag)?

設(shè)置套接字為阻塞或非阻塞模式:如果 flag 為 false,則將套接字設(shè)置為非阻塞,否則設(shè)置為阻塞。

本方法是某些 settimeout() 調(diào)用的簡(jiǎn)寫:

  • sock.setblocking(True) 相當(dāng)于 sock.settimeout(None)

  • sock.setblocking(False) 相當(dāng)于 sock.settimeout(0.0)

在 3.7 版更改: 本方法不再對(duì) socket.type 屬性設(shè)置 SOCK_NONBLOCK 標(biāo)志。

socket.settimeout(value)?

為阻塞套接字的操作設(shè)置超時(shí)。value 參數(shù)可以是非負(fù)浮點(diǎn)數(shù),表示秒,也可以是 None。如果賦為一個(gè)非零值,那么如果在操作完成前超過了超時(shí)時(shí)間 value,后續(xù)的套接字操作將拋出 timeout 異常。如果賦為 0,則套接字將處于非阻塞模式。如果指定為 None,則套接字將處于阻塞模式。

更多信息請(qǐng)查閱 關(guān)于套接字超時(shí)的說明

在 3.7 版更改: 本方法不再修改 socket.type 屬性的 SOCK_NONBLOCK 標(biāo)志。

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

設(shè)置給定套接字選項(xiàng)的值(參閱 Unix 手冊(cè)頁 setsockopt(2) )。所需的符號(hào)常量( SO_* 等)已定義在本 socket 模塊中。該值可以是整數(shù)、None 或表示緩沖區(qū)的 字節(jié)類對(duì)象。在后一種情況下,由調(diào)用者確保字節(jié)串中包含正確的數(shù)據(jù)位(關(guān)于將 C 結(jié)構(gòu)體編碼為字節(jié)串的方法,請(qǐng)參閱可選的內(nèi)置模塊 struct )。當(dāng) value 設(shè)置為 None 時(shí),必須設(shè)置 optlen 參數(shù)。這相當(dāng)于調(diào)用 setsockopt() C 函數(shù)時(shí)使用了 optval=NULLoptlen=optlen 參數(shù)。

在 3.5 版更改: 現(xiàn)在支持可寫的 字節(jié)類對(duì)象

在 3.6 版更改: 添加了 setsockopt(level, optname, None, optlen: int) 調(diào)用形式。

socket.shutdown(how)?

關(guān)閉一半或全部的連接。如果 howSHUT_RD,則后續(xù)不再允許接收。如果 howSHUT_WR,則后續(xù)不再允許發(fā)送。如果 howSHUT_RDWR,則后續(xù)的發(fā)送和接收都不允許。

socket.share(process_id)?

復(fù)制套接字,并準(zhǔn)備將其與目標(biāo)進(jìn)程共享。目標(biāo)進(jìn)程必須以 process_id 形式提供。然后可以利用某種形式的進(jìn)程間通信,將返回的字節(jié)對(duì)象傳遞給目標(biāo)進(jìn)程,還可以使用 fromshare() 在新進(jìn)程中重新創(chuàng)建套接字。一旦本方法調(diào)用完畢,就可以安全地將套接字關(guān)閉,因?yàn)椴僮飨到y(tǒng)已經(jīng)為目標(biāo)進(jìn)程復(fù)制了該套接字。

可用性: Windows。

3.3 新版功能.

注意此處沒有 read()write() 方法,請(qǐng)使用不帶 flags 參數(shù)的 recv()send() 來替代。

套接字對(duì)象還具有以下(只讀)屬性,這些屬性與傳入 socket 構(gòu)造函數(shù)的值相對(duì)應(yīng)。

socket.family?

套接字的協(xié)議簇

socket.type?

套接字的類型

socket.proto?

套接字的協(xié)議。

關(guān)于套接字超時(shí)的說明?

一個(gè)套接字對(duì)象可以處于以下三種模式之一:阻塞、非阻塞或超時(shí)。套接字默認(rèn)以阻塞模式創(chuàng)建,但是可以調(diào)用 setdefaulttimeout() 來更改。

  • blocking mode (阻塞模式)中,操作將阻塞,直到操作完成或系統(tǒng)返回錯(cuò)誤(如連接超時(shí))。

  • non-blocking mode (非阻塞模式)中,如果操作無法立即完成,則操作將失敗(不幸的是,不同系統(tǒng)返回的錯(cuò)誤不同):位于 select 中的函數(shù)可用于了解套接字何時(shí)以及是否可以讀取或?qū)懭搿?/p>

  • timeout mode (超時(shí)模式)下,如果無法在指定的超時(shí)內(nèi)完成操作(拋出 timeout 異常),或如果系統(tǒng)返回錯(cuò)誤,則操作將失敗。

注解

在操作系統(tǒng)層面上,超時(shí)模式 下的套接字在內(nèi)部都設(shè)置為非阻塞模式。同時(shí),阻塞和超時(shí)模式在文件描述符和套接字對(duì)象之間共享,這些描述符和對(duì)象均應(yīng)指向同一個(gè)網(wǎng)絡(luò)端點(diǎn)。如果,比如你決定使用套接字的 fileno(),這一實(shí)現(xiàn)細(xì)節(jié)可能導(dǎo)致明顯的結(jié)果。

超時(shí)與 connect 方法?

connect() 操作也受超時(shí)設(shè)置的約束,通常建議在調(diào)用 connect() 之前調(diào)用 settimeout(),或?qū)⒊瑫r(shí)參數(shù)直接傳遞給 create_connection()。但是,無論 Python 套接字超時(shí)設(shè)置如何,系統(tǒng)網(wǎng)絡(luò)棧都有可能返回自帶的連接超時(shí)錯(cuò)誤。

超時(shí)與 accept 方法?

如果 getdefaulttimeout() 的值不是 None,則 accept() 方法返回的套接字將繼承該超時(shí)值。若是 None,返回的套接字行為取決于偵聽套接字的設(shè)置:

  • 如果偵聽套接字處于 阻塞模式超時(shí)模式,則 accept() 返回的套接字處于 阻塞模式

  • 如果偵聽套接字處于 非阻塞模式,那么 accept() 返回的套接字是阻塞還是非阻塞取決于操作系統(tǒng)。如果要確保跨平臺(tái)時(shí)的正確行為,建議手動(dòng)覆蓋此設(shè)置。

示例?

以下是 4 個(gè)使用 TCP/IP 協(xié)議的最小示例程序:一臺(tái)服務(wù)器,它將收到的所有數(shù)據(jù)原樣返回(僅服務(wù)于一個(gè)客戶端),還有一個(gè)使用該服務(wù)器的客戶端。注意,服務(wù)器必須按序執(zhí)行 socket(), bind(), listen(), accept() (可能需要重復(fù)執(zhí)行 accept() 以服務(wù)多個(gè)客戶端),而客戶端僅需要按序執(zhí)行 socket(), connect()。還須注意,服務(wù)器不在偵聽套接字上發(fā)送 sendall()/recv(),而是在 accept() 返回的新套接字上發(fā)送。

前兩個(gè)示例僅支持 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))

下兩個(gè)例子與上兩個(gè)很像,但是同時(shí)支持 IPv4 和 IPv6。 服務(wù)端將監(jiān)聽第一個(gè)可用的地址族(它本應(yīng)同時(shí)監(jiān)聽兩個(gè))。 在大多數(shù)支持 IPv6 的系統(tǒng)上,IPv6 將有優(yōu)先權(quán)并且服務(wù)端可能不會(huì)接受 IPv4 流量。 客戶端將嘗試連接到作為名稱解析結(jié)果被返回的所有地址,并將流量發(fā)送給連接成功的第一個(gè)地址。

# 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 上使用原始套接字編寫一個(gè)非常簡(jiǎn)單的網(wǎng)絡(luò)嗅探器。 這個(gè)例子需要管理員權(quán)限來修改接口:

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 接口與采用原始套接字協(xié)議的 CAN 網(wǎng)絡(luò)進(jìn)行通信。 要改為通過廣播管理器協(xié)議來使用 CAN,則要用以下方式打開一個(gè) socket:

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

在綁定 (CAN_RAW) 或連接 (CAN_BCM) socket 之后,你將可以在 socket 對(duì)象上正常使用 socket.send() 以及 socket.recv() 操作(及同類操作)。

最后一個(gè)例子可能需要特別的權(quán)限:

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

如果多次運(yùn)行示例,且兩次運(yùn)行間隔很短,可能引發(fā)此錯(cuò)誤:

OSError: [Errno 98] Address already in use

這是因?yàn)榍耙淮芜\(yùn)行使套接字處于 TIME_WAIT 狀態(tài),無法立即重用。

要防止這種情況,需要設(shè)置一個(gè) socket 標(biāo)志 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 標(biāo)志告訴內(nèi)核將處于 TIME_WAIT 狀態(tài)的本地套接字重新使用,而不必等到固有的超時(shí)到期。

參見

關(guān)于套接字編程(C 語言)的介紹,請(qǐng)參閱以下文章:

  • An Introductory 4.3BSD Interprocess Communication Tutorial,作者 Stuart Sechrest

  • An Advanced 4.3BSD Interprocess Communication Tutorial,作者 Samuel J. Leffler et al,

兩篇文章都在 UNIX 開發(fā)者手冊(cè),補(bǔ)充文檔 1(第 PS1:7 和 PS1:8 節(jié))中。那些特定于平臺(tái)的參考資料,它們包含與套接字有關(guān)的各種系統(tǒng)調(diào)用,也是套接字語義細(xì)節(jié)的寶貴信息來源。對(duì)于 Unix,請(qǐng)參考手冊(cè)頁。對(duì)于 Windows,請(qǐng)參閱 WinSock(或 Winsock 2)規(guī)范。如果需要支持 IPv6 的 API,讀者可能希望參考 RFC 3493,標(biāo)題為 Basic Socket Interface Extensions for IPv6。